{"id":31476,"date":"2023-10-20T07:00:00","date_gmt":"2023-10-20T14:00:00","guid":{"rendered":"https:\/\/cloudinary.com\/blog\/?p=31476"},"modified":"2025-11-26T18:39:58","modified_gmt":"2025-11-27T02:39:58","slug":"build-chat-app-cloudinary-xata","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata","title":{"rendered":"Build a Chat App With Cloudinary and Xata"},"content":{"rendered":"\n<p>One common thing with platforms like WhatsApp, Telegram, and Instagram is that they all offer great chat functionality via their mobile and web applications. The ability to communicate swiftly with people across the globe has never been more important.<\/p>\n\n\n\n<p>In this article, we\u2018ll learn how to create a chat application with Next.js, Cloudinary&#8217;s Upload widget, and Xata.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#demo-and-source-code\"><\/a>Demo and Source Code<\/h2>\n\n\n\n<p>View the live demo via&nbsp;<a href=\"https:\/\/hackmamba-xata-chat-app.vercel.app\/?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\" target=\"_blank\" rel=\"noreferrer noopener\">this link<\/a>&nbsp;and access the source code on&nbsp;<a href=\"https:\/\/github.com\/nefejames\/hackmamba-xata-chat-app\/?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#prerequisites\"><\/a>Prerequisites<\/h2>\n\n\n\n<p>To follow along with this article, we need to have:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Knowledge of React and Next.js.<\/li>\n\n\n\n<li>A&nbsp;<a href=\"https:\/\/cloudinary.com\/users\/login?RelayState=%2Fconsole%2F%3Futm_campaign%3Dhackmamba-hackathon%26utm_medium%3Dhackmamba-blog%26utm_source%3Dhackmamba\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary account<\/a>.<\/li>\n\n\n\n<li>A&nbsp;<a href=\"https:\/\/app.xata.io\/signin\/?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\" target=\"_blank\" rel=\"noreferrer noopener\">Xata account<\/a>.<\/li>\n\n\n\n<li>Understanding of Chakra UI is advantageous but not required.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#what-is-xata\"><\/a>What is Xata?<\/h2>\n\n\n\n<p><a href=\"https:\/\/xata.io\/?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\" target=\"_blank\" rel=\"noreferrer noopener\">Xata<\/a>&nbsp;is a serverless database built on top of PostgreSQL and Elasticsearch. It comes with useful integrations with popular frameworks and technologies like Next.js, Netlify, Nuxt.js, Vercel, Remix, and SvelteKit.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#what-is-cloudinary\"><\/a>What is Cloudinary?<\/h2>\n\n\n\n<p><a href=\"https:\/\/cloudinary.com\/?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary<\/a>&nbsp;is a cloud-based and end-to-end platform with tools and functionalities for storing, processing, editing, managing, delivering, and transforming media assets.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#what-we-will-create\"><\/a>What We&#8217;ll Create<\/h2>\n\n\n\n<p>The screenshot below shows the application we&#8217;ll create.<\/p>\n\n\n\n<p>Users can fill in their name, provide a message and upload their avatar through the form on the right. After clicking <strong>Send<\/strong>, the data gets saved to Xata\u2019s database. We&#8217;ll fetch the chats from the database and display them on the left side of the application.<\/p>\n\n\n\n<p>The avatar image upload is handled by Cloudinary\u2019s Upload widget.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><a href=\"https:\/\/res.cloudinary.com\/practicaldev\/image\/fetch\/s--LAsGpr8X--\/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880\/https:\/\/paper-attachments.dropboxusercontent.com\/s_767BD3F7E260EFDC7E9C209798C513C5E8831A1EBE6D22594749206A5E483F79_1668165222225_Screenshot%2B2791.png\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1764210928\/blog-Build_a_Chat_App_With_Cloudinary_and_Xata-1.png\" alt=\"the chat app we will create\"\/><\/a><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#getting-started\"><\/a>Getting Started<\/h2>\n\n\n\n<p>Download, clone, or fork&nbsp;<a href=\"https:\/\/github.com\/nefejames\/hackmamba-xata-chat-app-ui\/?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\" target=\"_blank\" rel=\"noreferrer noopener\">this starter template<\/a>&nbsp;that contains the UI for the chat app.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    npx create-next-app xata-cloudinary-chat-app -e https:<span class=\"hljs-comment\">\/\/github.com\/nefejames\/hackmamba-xata-chat-app-ui<\/span>\n    or\n    yarn create next-app xata-cloudinary-chat-app -e https:<span class=\"hljs-comment\">\/\/github.com\/nefejames\/hackmamba-xata-chat-app-ui<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, navigate to the project directory, and run the command below to install Chakra UI, Next.js, Xata\u2019s SDK, and every other necessary dependency, then run the application.<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">    npm i\n<\/code><\/span><\/pre>\n\n\n<p>The starter template consists of the following files:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>components\/ChatContainer.js<\/code>. The container that holds the chats.<\/li>\n\n\n\n<li><code>components\/ChatInput.js<\/code>. Where users can input and submit new chats.<\/li>\n\n\n\n<li><code>components\/ChatProfile.js<\/code>. Holds each user\u2019s name, avatar, and chat message.<\/li>\n\n\n\n<li><code>layout\/index.js<\/code>. The layout for the application.<\/li>\n\n\n\n<li><code>utils<\/code>. This will hold the Xata instance and avatar upload logic, which we&#8217;ll set up later.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#setting-up-the-xata-database\"><\/a>Setting Up the Xata Database<\/h2>\n\n\n\n<p>We&#8217;ll start by creating a new database called&nbsp;<strong>chat-app<\/strong>&nbsp;on our Xata account.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/res.cloudinary.com\/practicaldev\/image\/fetch\/s--hbsQxY1Q--\/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880\/https:\/\/paper-attachments.dropboxusercontent.com\/s_767BD3F7E260EFDC7E9C209798C513C5E8831A1EBE6D22594749206A5E483F79_1668167312852_Screenshot_191.png\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1764210930\/blog-Build_a_Chat_App_With_Cloudinary_and_Xata-2.png\" alt=\"creating a new database in Xata\"\/><\/a><\/figure>\n\n\n\n<p>Next, create a&nbsp;<code>messages<\/code>&nbsp;table that will contain the records of the chat messages that users submit. Each record will have&nbsp;<code>message<\/code>,&nbsp;<code>author<\/code>,&nbsp;<code>img<\/code>, and&nbsp;<code>id<\/code>&nbsp;properties; the&nbsp;<code>id<\/code>&nbsp;is automatically generated by Xata.<\/p>\n\n\n\n<p>We&#8217;ll get the images from the media uploads in our Cloudinary account.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/res.cloudinary.com\/practicaldev\/image\/fetch\/s--mEsxU859--\/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880\/https:\/\/paper-attachments.dropboxusercontent.com\/s_767BD3F7E260EFDC7E9C209798C513C5E8831A1EBE6D22594749206A5E483F79_1668167558210_Screenshot_192.png\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1764210932\/blog-Build_a_Chat_App_With_Cloudinary_and_Xata-3.png\" alt=\"creating the messages records\"\/><\/a><\/figure>\n\n\n\n<p>The database schema is ready, so let\u2019s set up the Xata instance next, and integrate it into the application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#setting-up-the-xata-instance\"><\/a>Setting Up the Xata Instance<\/h2>\n\n\n\n<p>Run the command below to install the CLI globally.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css shcb-wrap-lines\">    <span class=\"hljs-selector-tag\">npm<\/span> <span class=\"hljs-selector-tag\">install<\/span> <span class=\"hljs-keyword\">@xata<\/span>.io\/cli -g\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Next, run&nbsp;<code>xata auth login<\/code>, which will prompt you to create a new API key in the browser or use an existing one; we\u2019ll go with the first option.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/res.cloudinary.com\/practicaldev\/image\/fetch\/s--zFCybS2K--\/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880\/https:\/\/paper-attachments.dropboxusercontent.com\/s_767BD3F7E260EFDC7E9C209798C513C5E8831A1EBE6D22594749206A5E483F79_1668174894564_xata-auth-login.png\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1764211132\/blog-Build_a_Chat_App_With_Cloudinary_and_Xata-6.png\" alt=\"login to create CLI API key\"\/><\/a><\/figure>\n\n\n\n<p>Once in the browser, give the API a name and click the&nbsp;<strong>Create API key<\/strong>&nbsp;button.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/res.cloudinary.com\/practicaldev\/image\/fetch\/s--f1jginGk--\/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880\/https:\/\/paper-attachments.dropboxusercontent.com\/s_767BD3F7E260EFDC7E9C209798C513C5E8831A1EBE6D22594749206A5E483F79_1668175038404_xata-create-new-api-key.png\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1764210934\/blog-Build_a_Chat_App_With_Cloudinary_and_Xata-4.png\" alt=\"creating a Xata API ley\"\/><\/a><\/figure>\n\n\n\n<p>Back on the dashboard, click the&nbsp;<strong>Get Code Snippet<\/strong>&nbsp;button at the top-right corner and copy the second command. We&#8217;ll use it to initialize the project locally with the aid of the CLI.<\/p>\n\n\n\n<p>Run the command in the terminal and choose from the configuration options. The screenshot below shows the configurations for this application.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/res.cloudinary.com\/practicaldev\/image\/fetch\/s--ZyUtlNKB--\/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880\/https:\/\/paper-attachments.dropboxusercontent.com\/s_767BD3F7E260EFDC7E9C209798C513C5E8831A1EBE6D22594749206A5E483F79_1668175900013_xata-cli-config.png\"><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/v1764210937\/blog-Build_a_Chat_App_With_Cloudinary_and_Xata-5.png\" alt=\"xata cli config\"\/><\/a><\/figure>\n\n\n\n<p>The CLI will automatically create a&nbsp;<code>xata.js<\/code>&nbsp;file that contains the&nbsp;<code>XataClient<\/code>&nbsp;instance we need. Let\u2019s move on to the coding aspects of the application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#fetching-the-messages-in-the-database\"><\/a>Fetching the Messages in the Database<\/h2>\n\n\n\n<p>We\u2019ll start by fetching the messages that already exist in the database. Update the&nbsp;<code>index.js<\/code>&nbsp;file with the following code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { Box, Flex, Heading } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@chakra-ui\/react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> ChatContainer <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@components\/ChatContainer\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> ChatInput <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@components\/ChatInput\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { getXataClient } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@utils\/xata\"<\/span>;\n\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Home<\/span>(<span class=\"hljs-params\">{ data }<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Heading<\/span> <span class=\"hljs-attr\">as<\/span>=<span class=\"hljs-string\">\"h1\"<\/span> <span class=\"hljs-attr\">mb<\/span>=<span class=\"hljs-string\">{5}<\/span>&gt;<\/span>\n            Xata Chat App\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Heading<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Flex<\/span> <span class=\"hljs-attr\">flexDir<\/span>=<span class=\"hljs-string\">{&#91;<\/span>\"<span class=\"hljs-attr\">column<\/span>\", \"<span class=\"hljs-attr\">row<\/span>\"]} <span class=\"hljs-attr\">justifyContent<\/span>=<span class=\"hljs-string\">\"space-between\"<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ChatContainer<\/span> <span class=\"hljs-attr\">chats<\/span>=<span class=\"hljs-string\">{data}<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Box<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ChatInput<\/span> \/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Box<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Flex<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n      );\n    }\n\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">getServerSideProps<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> xata = getXataClient();\n      <span class=\"hljs-keyword\">const<\/span> data = <span class=\"hljs-keyword\">await<\/span> xata.db.messages.getAll();\n      <span class=\"hljs-keyword\">return<\/span> { <span class=\"hljs-attr\">props<\/span>: { data } };\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here, we did the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Imported the&nbsp;<code>getXataClient<\/code>&nbsp;utility and initialized a new instance.<\/li>\n\n\n\n<li>Queried the&nbsp;<code>messages<\/code>&nbsp;table and fetched all records with&nbsp;<code>getServerSideProps<\/code>.<\/li>\n\n\n\n<li>Passed the fetched data to the&nbsp;<code>ChatContainer<\/code>&nbsp;component through props.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#displaying-the-messages-in-the-chatcontainer-component\"><\/a>Displaying the Messages in the ChatContainer Component<\/h2>\n\n\n\n<p>We&#8217;ll then loop through the data and display the individual messages in the UI.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { Box, VStack } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@chakra-ui\/react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> ChatProfile <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\".\/ChatProfile\"<\/span>;\n\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">ChatContainer<\/span>(<span class=\"hljs-params\">{ chats }<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Box<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">VStack<\/span> <span class=\"hljs-attr\">spacing<\/span>=<span class=\"hljs-string\">{5}<\/span>&gt;<\/span>\n            {chats.map((chat) =&gt; (\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ChatProfile<\/span>\n                <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{chat.id}<\/span>\n                <span class=\"hljs-attr\">author<\/span>=<span class=\"hljs-string\">{chat.author}<\/span>\n                <span class=\"hljs-attr\">img<\/span>=<span class=\"hljs-string\">{chat.img}<\/span>\n                <span class=\"hljs-attr\">message<\/span>=<span class=\"hljs-string\">{chat.message}<\/span>\n              \/&gt;<\/span>\n            ))}\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">VStack<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Box<\/span>&gt;<\/span><\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#setting-up-the-avatar-upload-functionality-in-the-chatinput-component\"><\/a>Setting Up Avatar Upload Functionality in ChatInput Component<\/h2>\n\n\n\n<p>When a user clicks the&nbsp;<strong>Upload Avatar<\/strong>&nbsp;button,&nbsp;<a href=\"https:\/\/cloudinary.com\/documentation\/upload_widget\/?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\" target=\"_blank\" rel=\"noreferrer noopener\">Cloudinary\u2019s Upload widget<\/a>&nbsp;will open, enabling the user to upload a picture. Let\u2019s set it up. Update the&nbsp;<code>ChatInput.js<\/code>&nbsp;file with the following code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { Box, Button, Input, Flex } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@chakra-ui\/react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> ShowImageUploadWidget <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@utils\/upload\"<\/span>;\n\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">ChatInput<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> &#91;imgUrl, setImgUrl] = useState(<span class=\"hljs-literal\">null<\/span>);\n\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Box<\/span> <span class=\"hljs-attr\">w<\/span>=<span class=\"hljs-string\">{&#91;<\/span>\"<span class=\"hljs-attr\">full<\/span>\", \"<span class=\"hljs-attr\">400px<\/span>\"]}&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Flex<\/span> <span class=\"hljs-attr\">flexDir<\/span>=<span class=\"hljs-string\">\"column\"<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Input<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"author\"<\/span> <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"Author\"<\/span> \/&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Input<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"newMessage\"<\/span> <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"Message\"<\/span> \/&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Button<\/span>\n                <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{()<\/span> =&gt;<\/span> ShowImageUploadWidget(setImgUrl)}\n              &gt;\n                Upload Avatar\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Button<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Button<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span>&gt;<\/span>Send<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Button<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Flex<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Box<\/span>&gt;<\/span><\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here, we did the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set up an&nbsp;<code>imgUrl<\/code>&nbsp;state that will contain the URL of the avatar users upload to Cloudinary.<\/li>\n\n\n\n<li>Imported a&nbsp;<code>ShowImageUploadWidget<\/code>&nbsp;function from the&nbsp;<code>utils<\/code>&nbsp;directory.<\/li>\n\n\n\n<li>Passed&nbsp;<code>ShowImageUploadWidget<\/code>&nbsp;to the&nbsp;<strong>Upload Avatar<\/strong>&nbsp;button\u2019s&nbsp;<code>onClick<\/code>&nbsp;event handler.<\/li>\n<\/ul>\n\n\n\n<p>The&nbsp;<code>ShowImageUploadWidget<\/code>&nbsp;function is responsible for the upload functionality. Create a&nbsp;<code>upload.js<\/code>&nbsp;file and paste the following code to set up&nbsp;<code>ShowImageUploadWidget<\/code>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">ShowImageUploadWidget<\/span>(<span class=\"hljs-params\">setImgUrl<\/span>) <\/span>{\n      <span class=\"hljs-built_in\">window<\/span>.cloudinary\n        .createUploadWidget(\n          {\n            <span class=\"hljs-attr\">cloudName<\/span>: <span class=\"hljs-string\">\"your-cloud-name\"<\/span>,\n            <span class=\"hljs-attr\">uploadPreset<\/span>: <span class=\"hljs-string\">\"ml_default\"<\/span>,\n          },\n          (error, result) =&gt; {\n            <span class=\"hljs-keyword\">if<\/span> (!error &amp;&amp; result &amp;&amp; result.event === <span class=\"hljs-string\">\"success\"<\/span>) {\n              setImgUrl(result.info.thumbnail_url);\n            }\n            <span class=\"hljs-keyword\">if<\/span> (error) {\n              <span class=\"hljs-built_in\">console<\/span>.log(error);\n            }\n          }\n        )\n        .open();\n    }\n\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> ShowImageUploadWidget;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><br><strong>JavaScript<\/strong><\/p>\n\n\n\n<p>Let\u2019s breakdown the snippet above:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>ShowImageUploadWidget<\/code>&nbsp;calls the&nbsp;<code>createUploadWidget<\/code>&nbsp;that exists in the&nbsp;<code>cloudinary<\/code>&nbsp;object.<\/li>\n\n\n\n<li><code>createUploadWidget<\/code>&nbsp;takes in our&nbsp;<code>cloudname<\/code>&nbsp;as part of its config.<\/li>\n\n\n\n<li><code>ShowImageUploadWidget<\/code>&nbsp;accepts the&nbsp;<code>setImgUrl<\/code>&nbsp;function as an argument. If an avatar is uploaded successfully, the&nbsp;<code>imgUrl<\/code>&nbsp;state will be updated with the URL of the avatar a user uploads.<\/li>\n<\/ul>\n\n\n\n<p>We&#8217;ll have to load the widget\u2019s script in order for it to work. Next.js provides a&nbsp;<code>[Script](https:\/\/nextjs.org\/docs\/basic-features\/script)<\/code>&nbsp;<a href=\"https:\/\/nextjs.org\/docs\/basic-features\/script\/?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\" target=\"_blank\" rel=\"noreferrer noopener\">component<\/a>&nbsp;that we can use to load third-party scripts in our application.<\/p>\n\n\n\n<p>Update the&nbsp;<code>_app.js<\/code>&nbsp;file with the following code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { ChakraProvider } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@chakra-ui\/react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> Wrapper <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@layout\/index\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> Script <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"next\/script\"<\/span>;\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">MyApp<\/span>(<span class=\"hljs-params\">{ Component, pageProps }<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ChakraProvider<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Script<\/span>\n            <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/upload-widget.cloudinary.com\/global\/all.js\"<\/span>\n            <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\/javascript\"<\/span>\n            <span class=\"hljs-attr\">strategy<\/span>=<span class=\"hljs-string\">\"beforeInteractive\"<\/span>\n          \/&gt;<\/span><span class=\"handlebars\"><span class=\"xml\">\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Wrapper<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Component<\/span> {<span class=\"hljs-attr\">...pageProps<\/span>} \/&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Wrapper<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ChakraProvider<\/span>&gt;<\/span><\/span><\/span><\/span>\n      );\n    }\n\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> MyApp;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here, we&#8217;ll import the&nbsp;<code>Script<\/code>&nbsp;component from Next.js and use it to load the widget\u2019s script.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#setting-up-the-form-submission-functionality-in-the-chatinput-component\"><\/a>Setting Up Form Submission Functionality in ChatInput Component<\/h2>\n\n\n\n<p>The form submission functionality is the last thing we need to set up. Update the&nbsp;<code>ChatInput<\/code>&nbsp;component with the following code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> { Box, Button, Input, Flex, useToast } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@chakra-ui\/react\"<\/span>;\n    <span class=\"hljs-keyword\">import<\/span> ShowImageUploadWidget <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@utils\/upload\"<\/span>;\n\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">ChatInput<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n      <span class=\"hljs-keyword\">const<\/span> toast = useToast();\n      <span class=\"hljs-keyword\">const<\/span> &#91;imgUrl, setImgUrl] = useState(<span class=\"hljs-literal\">null<\/span>);\n\n      <span class=\"hljs-keyword\">const<\/span> handleSubmit = <span class=\"hljs-keyword\">async<\/span> (e) =&gt; {\n        e.preventDefault();\n        <span class=\"hljs-keyword\">const<\/span> formData = <span class=\"hljs-keyword\">new<\/span> FormData(e.target);\n        <span class=\"hljs-keyword\">const<\/span> data = <span class=\"hljs-built_in\">Object<\/span>.fromEntries(formData);\n        <span class=\"hljs-keyword\">const<\/span> author = data.author;\n        <span class=\"hljs-keyword\">const<\/span> newMessage = data.newMessage;\n        fetch(<span class=\"hljs-string\">\"\/api\/add-message\"<\/span>, {\n          <span class=\"hljs-attr\">method<\/span>: <span class=\"hljs-string\">\"POST\"<\/span>,\n          <span class=\"hljs-attr\">headers<\/span>: {\n            <span class=\"hljs-string\">\"Content-Type\"<\/span>: <span class=\"hljs-string\">\"application\/json\"<\/span>,\n          },\n          <span class=\"hljs-attr\">body<\/span>: <span class=\"hljs-built_in\">JSON<\/span>.stringify({\n            author,\n            newMessage,\n            imgUrl,\n          }),\n        });\n        e.target.reset();\n        toast({\n          <span class=\"hljs-attr\">title<\/span>: <span class=\"hljs-string\">\"Message created.\"<\/span>,\n          <span class=\"hljs-attr\">description<\/span>: <span class=\"hljs-string\">\"Message sent to chat db.\"<\/span>,\n        });\n      };\n\n      <span class=\"hljs-keyword\">return<\/span> (\n        <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Box<\/span> <span class=\"hljs-attr\">w<\/span>=<span class=\"hljs-string\">{&#91;<\/span>\"<span class=\"hljs-attr\">full<\/span>\", \"<span class=\"hljs-attr\">400px<\/span>\"]}&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">onSubmit<\/span>=<span class=\"hljs-string\">{handleSubmit}<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Flex<\/span> <span class=\"hljs-attr\">flexDir<\/span>=<span class=\"hljs-string\">\"column\"<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Input<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"author\"<\/span> <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"Author\"<\/span> \/&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Input<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"newMessage\"<\/span> <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"Message\"<\/span> \/&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Button<\/span>&gt;<\/span>\n                Upload Avatar\n              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Button<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Button<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span>&gt;<\/span>Send<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Button<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Flex<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Box<\/span>&gt;<\/span><\/span>\n      );\n    }\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here, we did the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Created a&nbsp;<code>handleSubmit<\/code>&nbsp;function that takes the form data and passes it on the&nbsp;<code>add-messages<\/code>&nbsp;route. The&nbsp;<code>add-messages<\/code>&nbsp;will handle pushing the form data to the Xata database; we will set up the route next<\/li>\n\n\n\n<li>Used the&nbsp;<code>toast<\/code>&nbsp;method to display a message upon successful form submission.<\/li>\n\n\n\n<li>Passed&nbsp;<code>handleSubmit<\/code>&nbsp;to the form\u2019s&nbsp;<code>onSubmit<\/code>&nbsp;event handler.<\/li>\n<\/ul>\n\n\n\n<p>For the API route, create a&nbsp;<code>api\/add-message.js<\/code>&nbsp;file and paste the following code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">    <span class=\"hljs-keyword\">import<\/span> { getXataClient } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">\"@utils\/xata\"<\/span>;\n    <span class=\"hljs-keyword\">const<\/span> xata = getXataClient();\n\n    <span class=\"hljs-keyword\">const<\/span> handler = <span class=\"hljs-keyword\">async<\/span> (req, res) =&gt; {\n      <span class=\"hljs-keyword\">const<\/span> { author, newMessage, imgUrl } = req.body;\n      <span class=\"hljs-keyword\">await<\/span> xata.db.messages.create({\n        <span class=\"hljs-attr\">author<\/span>: author,\n        <span class=\"hljs-attr\">message<\/span>: newMessage,\n        <span class=\"hljs-attr\">img<\/span>: imgUrl,\n      });\n      res.end();\n    };\n\n    <span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> handler;\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here, we did the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Imported the&nbsp;<code>getXataClient<\/code>&nbsp;utility and initialized a new instance.<\/li>\n\n\n\n<li>Accessed the&nbsp;<code>author<\/code>,&nbsp;<code>newMessage<\/code>, and&nbsp;<code>imgUrl<\/code>&nbsp;from the request\u2019s body.<\/li>\n\n\n\n<li>Saved the new chat data to the&nbsp;<code>messages<\/code>&nbsp;table on Xata.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#conclusion\"><\/a>Conclusion<\/h2>\n\n\n\n<p>With that, we&#8217;ve successfully created a chat application with Cloudinary and Xata. The purpose of this simple is to give a brief overview of the features of these awesome technologies. We can take the project to the next step by validating the form fields during submission and adding user authentication and real-time functionality to the application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><a href=\"https:\/\/dev.to\/hackmamba\/build-a-chat-app-with-cloudinary-and-xata-30o7#resources\"><\/a>Resources<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/cloudinary.com\/documentation\/upload_widget\">Cloudinary&#8217;s Upload widget documentation<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/nextjs.org\/docs\/basic-features\/script\/?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\" target=\"_blank\" rel=\"noreferrer noopener\">Next Script documentation<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/xata.io\/docs\/overview\/?utm_source=hackmamba&amp;utm_campaign=hackmamba-hackathon&amp;utm_medium=hackmamba-blog\">Xata documentation<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>One common thing with platforms like WhatsApp, Telegram, and Instagram is that they all offer great chat functionality via their mobile and web applications. The ability to communicate swiftly with people across the globe has never been more important. In this article, we\u2018ll learn how to create a chat application with Next.js, Cloudinary&#8217;s Upload widget, [&hellip;]<\/p>\n","protected":false},"author":87,"featured_media":31478,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[212,373],"class_list":["post-31476","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-next-js","tag-upload"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Build a Chat App With Cloudinary and Xata<\/title>\n<meta name=\"description\" content=\"Learn how to create a chat application with Next.js, Cloudinary&#039;s Upload widget, and Xata\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Build a Chat App With Cloudinary and Xata\" \/>\n<meta property=\"og:description\" content=\"Learn how to create a chat application with Next.js, Cloudinary&#039;s Upload widget, and Xata\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2023-10-20T14:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-11-27T02:39:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"1100\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"melindapham\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata\"},\"author\":{\"name\":\"melindapham\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\"},\"headline\":\"Build a Chat App With Cloudinary and Xata\",\"datePublished\":\"2023-10-20T14:00:00+00:00\",\"dateModified\":\"2025-11-27T02:39:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata\"},\"wordCount\":1141,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA\",\"keywords\":[\"Next.js\",\"Upload\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2023\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata\",\"url\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata\",\"name\":\"Build a Chat App With Cloudinary and Xata\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA\",\"datePublished\":\"2023-10-20T14:00:00+00:00\",\"dateModified\":\"2025-11-27T02:39:58+00:00\",\"description\":\"Learn how to create a chat application with Next.js, Cloudinary's Upload widget, and Xata\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA\",\"width\":2000,\"height\":1100},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Build a Chat App With Cloudinary and Xata\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9\",\"name\":\"melindapham\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g\",\"caption\":\"melindapham\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Build a Chat App With Cloudinary and Xata","description":"Learn how to create a chat application with Next.js, Cloudinary's Upload widget, and Xata","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata","og_locale":"en_US","og_type":"article","og_title":"Build a Chat App With Cloudinary and Xata","og_description":"Learn how to create a chat application with Next.js, Cloudinary's Upload widget, and Xata","og_url":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata","og_site_name":"Cloudinary Blog","article_published_time":"2023-10-20T14:00:00+00:00","article_modified_time":"2025-11-27T02:39:58+00:00","og_image":[{"width":2000,"height":1100,"url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA","type":"image\/jpeg"}],"author":"melindapham","twitter_card":"summary_large_image","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata"},"author":{"name":"melindapham","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9"},"headline":"Build a Chat App With Cloudinary and Xata","datePublished":"2023-10-20T14:00:00+00:00","dateModified":"2025-11-27T02:39:58+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata"},"wordCount":1141,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA","keywords":["Next.js","Upload"],"inLanguage":"en-US","copyrightYear":"2023","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata","url":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata","name":"Build a Chat App With Cloudinary and Xata","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA","datePublished":"2023-10-20T14:00:00+00:00","dateModified":"2025-11-27T02:39:58+00:00","description":"Learn how to create a chat application with Next.js, Cloudinary's Upload widget, and Xata","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA","width":2000,"height":1100},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/build-chat-app-cloudinary-xata#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Build a Chat App With Cloudinary and Xata"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/0d5ad601e4c3b5be89245dfb14be42d9","name":"melindapham","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/e6f989fa97fe94be61596259d8629c3df65aec4c7da5c0000f90d810f313d4f4?s=96&d=mm&r=g","caption":"melindapham"}}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1696620194\/Blog-Hackmamba_Building_a_ChatApp\/Blog-Hackmamba_Building_a_ChatApp.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/31476","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/87"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=31476"}],"version-history":[{"count":5,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/31476\/revisions"}],"predecessor-version":[{"id":39448,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/31476\/revisions\/39448"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/31478"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=31476"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=31476"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=31476"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}