<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Obisike Treasure</title>
    <description>The latest articles on DEV Community by Obisike Treasure (@otrex).</description>
    <link>https://dev.to/otrex</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F465581%2F4a421b67-0fd3-4dfc-aacf-4be35e37ae71.jpeg</url>
      <title>DEV Community: Obisike Treasure</title>
      <link>https://dev.to/otrex</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/otrex"/>
    <language>en</language>
    <item>
      <title>Steps to manipulating MongoDB with AI</title>
      <dc:creator>Obisike Treasure</dc:creator>
      <pubDate>Tue, 07 Jan 2025 17:12:26 +0000</pubDate>
      <link>https://dev.to/hackmamba/steps-to-manipulating-mongodb-with-ai-175i</link>
      <guid>https://dev.to/hackmamba/steps-to-manipulating-mongodb-with-ai-175i</guid>
      <description>&lt;p&gt;&lt;em&gt;Meta: Integrate AI into your MongoDB workflow with Cody. This tutorial helps you automate database tasks, create queries, and manage data more effectively in VSCode.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mongodb.com/" rel="noopener noreferrer"&gt;MongoDB&lt;/a&gt; has become a popular choice for developers, offering features like time series data, full-text search, vector search, and aggregation pipelines. Since its introduction in 2007, it has been downloaded over &lt;a href="https://investors.mongodb.com/news-releases/news-release-details/mongodb-inc-announces-fourth-quarter-and-full-year-fiscal-2023" rel="noopener noreferrer"&gt;365 million&lt;/a&gt; times, largely due to its open-source development model.&lt;/p&gt;

&lt;p&gt;However, working with MongoDB‘s features, such as replica sets and built-in replication, can sometimes be challenging. Advanced querying, building complex aggregations, and managing tasks like indexing or replication through its integrated set of related services can become cumbersome and time-consuming.&lt;/p&gt;

&lt;p&gt;That is where &lt;a href="https://sourcegraph.com/cody" rel="noopener noreferrer"&gt;Sourcegraph&lt;/a&gt;‘&lt;a href="https://sourcegraph.com/cody" rel="noopener noreferrer"&gt;s Cody&lt;/a&gt; comes in. Cody is an AI assistant designed to streamline development tasks by helping you &lt;strong&gt;generate efficient queries&lt;/strong&gt;, &lt;strong&gt;simplify aggregation creation&lt;/strong&gt;, and &lt;strong&gt;manage key operations like indexing and replication&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this tutorial, you will learn how to integrate AI into your MongoDB project. You will be guided through using Cody to write queries, perform aggregations, and manage database operations step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along, you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Visual Studio Code (VSCode)&lt;/strong&gt;&lt;/a&gt;: Ensure it is installed as your code editor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basic MongoDB knowledge&lt;/strong&gt;: Familiarity with MongoDB is needed to follow the tutorial effectively.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript knowledge&lt;/strong&gt;: Basic JavaScript skills are required for scripting and writing uncomplicated queries.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setting up the environment
&lt;/h2&gt;

&lt;p&gt;To continue with the tutorial, you must install and set up both MongoDB and Cody in your code editor (VSCode).&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing and setting up MongoDB
&lt;/h3&gt;

&lt;p&gt;Start by installing the MongoDB server. For instructions specific to your operating system, refer to the official &lt;a href="https://www.mongodb.com/docs/manual/installation/" rel="noopener noreferrer"&gt;MongoDB installation documentation&lt;/a&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: For this tutorial, install the MongoDB community edition.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Follow the guide that matches your operating system to get MongoDB running. You can also use MongoDB Atlas, the cloud-hosted database service.&lt;/p&gt;

&lt;p&gt;Next, install the official MongoDB extension for VS Code to interact with your locally hosted MongoDB server. Search for &lt;strong&gt;“MongoDB for VS Code”&lt;/strong&gt; in the extensions section, or use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=mongodb.mongodb-vscode" rel="noopener noreferrer"&gt;MongoDB extension link&lt;/a&gt; to get it from the marketplace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8pbdwgxdv830qssonbel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8pbdwgxdv830qssonbel.png" alt="Screenshot of the VS Code MongoDB marketplace" width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Install&lt;/strong&gt; when you find the extension. After installation, you will need to connect your MongoDB extension to your local MongoDB server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connecting your MongoDB server to the extension
&lt;/h3&gt;

&lt;p&gt;To connect your VSCode MongoDB client to the database server, you'll need the &lt;strong&gt;host address&lt;/strong&gt;, &lt;strong&gt;port number&lt;/strong&gt;, and &lt;strong&gt;password&lt;/strong&gt;. For the community edition, your host address is usually &lt;strong&gt;localhost&lt;/strong&gt;, and the port is &lt;strong&gt;27017&lt;/strong&gt;, provided the MongoDB server is running, and the port is available.&lt;/p&gt;

&lt;p&gt;Open the MongoDB extension from the sidebar in VSCode.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11lrl3d1lwx2bufd8tpl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11lrl3d1lwx2bufd8tpl.png" alt="Screenshot of the MongoDB extension icon in VSCode" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Add Connection&lt;/strong&gt; to create a new connection.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xc4a8gbq4r0re5ijsfj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xc4a8gbq4r0re5ijsfj.png" alt="Screenshot of the Add Connection button" width="800" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click &lt;strong&gt;Open form&lt;/strong&gt; to enter your credentials (host, port, and password if needed).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22ci5ev7cuqdju6fkjii.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22ci5ev7cuqdju6fkjii.png" alt="Screenshot of the Open form button" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Save &amp;amp; Connect&lt;/strong&gt;, then update the &lt;strong&gt;URI&lt;/strong&gt; field with your credentials in the format below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mongodb://&amp;lt;host&amp;gt;:&amp;lt;port&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0l8wqr8k7kev6esu5wi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0l8wqr8k7kev6esu5wi.png" alt="Screenshot of the Save &amp;amp; Connect button" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your MongoDB setup is now complete.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmiei1lty3b45w1e4m2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmiei1lty3b45w1e4m2j.png" alt="Screenshot of the completed MongoDB setup" width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you will create a playground to run your MongoDB commands. Click &lt;strong&gt;Create New Playground&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbs521c4omcdvnlirxvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbs521c4omcdvnlirxvc.png" alt="Screenshot of the Create New Playground button" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will generate a &lt;code&gt;playground-1.mongodb.js&lt;/code&gt; file where you can write and test your commands.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqoouyj5xg75ulkx1xy5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqoouyj5xg75ulkx1xy5.png" alt="Screenshot of the created playground" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Delete the file content, keeping only &lt;code&gt;use("mongdbVSCodePlaygroundDB")&lt;/code&gt;, which specifies the database for the playground.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5um4ohy6vji8jldlahe6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5um4ohy6vji8jldlahe6.png" alt="Screenshot of the cleared playground" width="800" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you’ve completed the setup for MongoDB let’s proceed to set up Cody in your VSCode environment.&lt;/p&gt;
&lt;h3&gt;
  
  
  Installing and configuring Cody
&lt;/h3&gt;

&lt;p&gt;Cody supports multiple development environments, including JetBrains IntelliJ and VSCode. To install it in VSCode, open the VSCode Marketplace and search for “&lt;strong&gt;Cody AI”&lt;/strong&gt; in the extensions search bar. Locate the Cody extension as shown below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvy9zhre5dg8a3sm5duu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvy9zhre5dg8a3sm5duu.png" alt="Screenshot of the Cody extension in search results" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once located, select &lt;strong&gt;Install&lt;/strong&gt; to add Cody to your VSCode setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kpdibbjkmfhbzs73r1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9kpdibbjkmfhbzs73r1o.png" alt="Screenshot of Cody" width="800" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you do not have an account, &lt;a href="https://sourcegraph.com/cody" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://sourcegraph.com/cody" rel="noopener noreferrer"&gt;create one to access Cody&lt;/a&gt;. &lt;br&gt;
Follow the on-screen instructions to sign in and start coding with Cody.&lt;/p&gt;
&lt;h2&gt;
  
  
  Writing MongoDB operations, queries, and aggregations
&lt;/h2&gt;

&lt;p&gt;While MongoDB offers a flexible database language, writing queries manually can often lead to errors and take up a significant amount of time, particularly for complex operations. Let’s look at how you can perform the following operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;InsertMany&lt;/li&gt;
&lt;li&gt;Find&lt;/li&gt;
&lt;li&gt;Aggregations&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  InsertMany Operation
&lt;/h3&gt;

&lt;p&gt;For example, suppose you have a collection called &lt;code&gt;students&lt;/code&gt; and need to insert around 30 records from a JSON or CSV file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual approach:&lt;/strong&gt; You would need to format all the records as an array of objects, ensuring that each entry matches the fields in the collection. This might look something like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; 
       &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mike&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Owen&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="na"&gt;grade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="na"&gt;houseNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="na"&gt;nextOfKin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ben&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
       &lt;span class="c1"&gt;// additional fields...&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; 
       &lt;span class="na"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Patrick&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="na"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Elijah&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="na"&gt;grade&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="na"&gt;houseNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
       &lt;span class="na"&gt;nextOfKin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ben&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
       &lt;span class="c1"&gt;// additional fields...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// more records...&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;students&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Manually entering data in this format can be tedious and error-prone, especially when dealing with large datasets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cody’s approach:&lt;/strong&gt; With Cody, streamlining this process is simple. Copy the data from your file, then press &lt;strong&gt;Opt + K&lt;/strong&gt; (or &lt;strong&gt;Alt + K&lt;/strong&gt;) or right-click, select &lt;strong&gt;Cody&lt;/strong&gt;, and choose &lt;strong&gt;Edit code&lt;/strong&gt; to open the Edit Code interface.&lt;/p&gt;

&lt;p&gt;Next, type in the following instructions:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Write a MongoDB query to insert &lt;span class="sb"&gt;`&amp;lt;paste your data here&amp;gt;`&lt;/span&gt; into the student's collection.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here is a video on how you can perform the &lt;strong&gt;insertMany&lt;/strong&gt; using Cody.&lt;/p&gt;


&lt;div&gt;
  &lt;iframe src="https://loom.com/embed/25b5f42931c442248428455a384ed4c8"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;



&lt;p&gt;Cody will generate the query for you. Simply click &lt;strong&gt;Accept&lt;/strong&gt; to confirm the generated code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xuk2ksc8jw9mywidqk5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xuk2ksc8jw9mywidqk5.png" alt="Cody’s Accept button" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can then run the code by clicking on the play icon in the playground.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe8w7yui6g9v6de0l10zk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe8w7yui6g9v6de0l10zk.png" alt="Playground code runner" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Find Query
&lt;/h3&gt;

&lt;p&gt;Let’s say you need to retrieve all students with a GPA above 3.5 who enrolled between March and November. Here is how to do it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual approach:&lt;/strong&gt; You might use the &lt;code&gt;find&lt;/code&gt; method to handle this query. However, dealing with date ranges in MongoDB can get tricky, especially when you need to match specific months.&lt;/p&gt;

&lt;p&gt;Here is an example of what you might come up with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;students&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;gpa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$gt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;3.5&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;enrolmentDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1900-03-01T00:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;$lt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3000-12-01T00:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While this query seems to work, it has some potential issues; first, it won't fetch data beyond the year 3000. Additionally, the query retrieves data based on the date rather than specifically targeting the month. If you're not highly experienced with MongoDB, finding the correct function can be challenging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cody approach:&lt;/strong&gt; With Cody, you can open the Edit interface once again, then type:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Write a query to fetch all students with a GPA above 3.5 and an enrolment date between March and November.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Cody generates the query for you, saving time and effort, as demonstrated in the video below.&lt;/p&gt;


&lt;div&gt;
  &lt;iframe src="https://loom.com/embed/0e3d26078efd446884caf22753eb3385"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;



&lt;p&gt;Similarly, you can do the same for the &lt;strong&gt;update&lt;/strong&gt;, &lt;strong&gt;updateMany,&lt;/strong&gt; and &lt;strong&gt;delete&lt;/strong&gt; operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performing Aggregations
&lt;/h3&gt;

&lt;p&gt;The aggregation pipeline allows you to perform more complex queries and subqueries.&lt;br&gt;
Let's say you need to calculate the average GPA of students who enrolled between March and November and group them by their enrollment year. Aggregation can be complex, especially when you're trying to perform calculations or grouping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual approach&lt;/strong&gt;: You would have to use the &lt;code&gt;aggregate&lt;/code&gt; method to group and calculate, possibly using multiple stages like &lt;code&gt;$match&lt;/code&gt;, &lt;code&gt;$group&lt;/code&gt;, and &lt;code&gt;$project&lt;/code&gt;. This can be quite challenging if you‘re not familiar with MongoDB's aggregation framework.&lt;/p&gt;

&lt;p&gt;Here is an example of what you might come up with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;students&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;enrollment_date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1900-03-01T00:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;$lt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3000-12-01T00:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$enrollment_date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;averageGPA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$avg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$gpa&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;enrolmentYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;averageGPA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While this works, it involves multiple stages and requires some knowledge of the MongoDB aggregation pipeline. Getting it right can be tricky, especially when working with date ranges and grouping data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cody’s approach&lt;/strong&gt;: With Cody, you can just open the Edit interface and type:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Write an aggregation query to group students by the year they enrolled, calculate the average GPA for each group, and only consider students who enrolled between March and November.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Next, Cody generates the aggregation pipeline:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;students&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;$expr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;$and&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$gte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;$month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$enrollment_date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$lte&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt; &lt;span class="na"&gt;$month&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$enrollment_date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$group&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$year&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$enrollment_date&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;averageGPA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$avg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$gpa&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$project&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;enrollmentYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;averageGPA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;$round&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;$averageGPA&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;$sort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;enrollmentYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Here is a video of Cody in action. &lt;/p&gt;


&lt;div&gt;
  &lt;iframe src="https://loom.com/embed/56cdc849db4a4dc197d64d63432cacae"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating Cody’s custom command to help with writing queries and operations
&lt;/h2&gt;

&lt;p&gt;Creating Cody’s custom command allows you to automate tasks related to your MongoDB database interactions, making your workflow more efficient. These commands can be fine-tuned to generate, optimize, or refactor data requests, all while leveraging Cody's context-aware capabilities to ensure they fit seamlessly within your codebase.&lt;/p&gt;

&lt;p&gt;Let's create one. First, click the Cody extension icon:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdu89lxy3ltp7vf1vz9e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdu89lxy3ltp7vf1vz9e.png" alt="Cody extension icon" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click &lt;strong&gt;Manage&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fac39au4uvuzyabtxp7n1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fac39au4uvuzyabtxp7n1.png" alt="Manage button" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, click &lt;strong&gt;New Custom Command:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqh1hsjfs08g6prhvqagq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqh1hsjfs08g6prhvqagq.png" alt="New Custom Command button" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;“MongoDBExpert”&lt;/strong&gt; as the command name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fi6jw5pvsqg2i1zhd55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fi6jw5pvsqg2i1zhd55.png" alt="Entering MongoDBExpert as the command name" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Ask&lt;/strong&gt; for the command mode, which controls how Cody interacts with the editor (VSCode):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F608w1ohrisc2glhh42n8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F608w1ohrisc2glhh42n8.png" alt="Selecting Ask mode" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, enter the following  prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;You are a MongoDB expert skilled in writing optimized queries, operations, and aggregation pipelines. You provide practical advice on managing tasks like sharding, replication, and indexing to improve performance and scalability.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above prompt tells Cody to assume a role as an expert in MongoDB. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0414mrlrhyolsfivofy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0414mrlrhyolsfivofy.png" alt="Entering the instruction for the command" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ensure that &lt;strong&gt;Selected Code&lt;/strong&gt; and &lt;strong&gt;Current File&lt;/strong&gt; are both checked so the command has access to the highlighted source code and the current file you are working with:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F71l846fay00eeiv6pava.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F71l846fay00eeiv6pava.png" alt="Selecting context options" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose &lt;strong&gt;Workspace Settings&lt;/strong&gt; to store the command for this workspace:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8vs273pxx198ovqbdoss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8vs273pxx198ovqbdoss.png" alt="Choosing Workspace Settings" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your Cody command is ready and can be used within the project's workspace.&lt;/p&gt;
&lt;h3&gt;
  
  
  Updating operation using the command
&lt;/h3&gt;

&lt;p&gt;Building on our previous example with &lt;code&gt;student&lt;/code&gt; records, imagine you need to update the expected graduation dates for students born in March by adding five years. You need to perform the following actions. &lt;/p&gt;

&lt;p&gt;First, click the Cody extension icon and select the &lt;strong&gt;MongoDBExpert&lt;/strong&gt; command:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fozrrau1roiryypb40lxr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fozrrau1roiryypb40lxr.png" alt="Selecting MongoDBExpert command" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the chat box, type:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Write an operation to update the students database so that for every student born in March, add 5 more years to their expected_graduation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr8dee139s5ejwt72z10.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkr8dee139s5ejwt72z10.png" alt="Entering the query in Cody's chat" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Play&lt;/strong&gt; icon to execute the instruction:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pq68s2mazzwj4svdf5b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1pq68s2mazzwj4svdf5b.png" alt="Clicking the Play icon" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, click Copy, then paste it into your playground to test:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo57bf16pvyft9az5x6o5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo57bf16pvyft9az5x6o5.png" alt="Copying and pasting the code" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Managing MongoDB operations
&lt;/h2&gt;

&lt;p&gt;Managing MongoDB operations involves various tasks, including indexing and replication. Understanding and effectively utilizing these tasks is crucial for maintaining the performance, availability, and scalability of your MongoDB database.&lt;/p&gt;
&lt;h3&gt;
  
  
  Indexing
&lt;/h3&gt;

&lt;p&gt;Indexes improve query performance by allowing MongoDB to quickly locate data without scanning every document in a collection. Here's how you can work with indexes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual approach&lt;/strong&gt;: To create indexes, you must be aware of the data points that affect the speed of querying information. For example, you can create an index with the following command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;students&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createIndex&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;enrollment_date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While this works, it's not necessarily the most efficient approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cody’s approach&lt;/strong&gt;: You can leverage Cody to optimize this process. First, activate Cody‘s chat by using &lt;strong&gt;Opt + L&lt;/strong&gt; (or &lt;strong&gt;Alt + L&lt;/strong&gt;). Cody will automatically access the context of your playground file.&lt;/p&gt;

&lt;p&gt;Enter the following prompt:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Given that I would mostly be trying to get students by their enrollment_date, name, and probably by when they graduate and their GPA, suggest the best approach to indexing.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After that, Cody will provide an optimized solution and a step-by-step guide to implementing your indexing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxzziokr3rkb60p3d5b9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxzziokr3rkb60p3d5b9u.png" alt="Screenshot showing the result from Cody" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can then click on &lt;strong&gt;Apply&lt;/strong&gt; to add these changes to your file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2tljas14y41tzh3cj4p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu2tljas14y41tzh3cj4p.png" alt="Screenshot of the Apply button" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the Code Indexing code generated by Cody.&lt;/p&gt;

&lt;p&gt;Here is the final result:&lt;/p&gt;


&lt;div&gt;
  &lt;iframe src="https://loom.com/embed/04b03bc2d16448228ea9bdf64699cde2"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Replication
&lt;/h3&gt;

&lt;p&gt;Replication involves creating copies of your data across multiple servers to ensure redundancy, high availability, and fault tolerance. Here’s how you can perform replication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Manual approach&lt;/strong&gt;: To set up replication, you must decide the number of servers based on your available resources and database load. Then, perform the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spin up different instances of MongoDB:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# On server 1:
&lt;/span&gt;&lt;span class="n"&gt;mongod&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;replSet&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rs0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bind_ip&lt;/span&gt; &lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server1_ip&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;27017&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;dbpath&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;db1&lt;/span&gt;

&lt;span class="c1"&gt;# On server 2:
&lt;/span&gt;&lt;span class="n"&gt;mongod&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;replSet&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rs0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bind_ip&lt;/span&gt; &lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server2_ip&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;27017&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;dbpath&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;db2&lt;/span&gt;

&lt;span class="c1"&gt;# On server 3:
&lt;/span&gt;&lt;span class="n"&gt;mongod&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;replSet&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rs0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bind_ip&lt;/span&gt; &lt;span class="n"&gt;localhost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server3_ip&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="mi"&gt;27017&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;dbpath&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;db3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Connect to one instance and configure the replica set:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;rs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initiate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rs0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;members&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server1_ip:27017&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server2_ip:27017&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server3_ip:27017&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You may encounter issues such as determining the appropriate number of replicas, choosing the best approach for handling read and write within the replica set, and ensuring optimal replication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cody's approach&lt;/strong&gt;: To simplify this process, use a custom command in Cody. Navigate to the custom command section and enter the following prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;What is the best approach to setting up replication in MongoDB for a students database that requires high availability and minimal downtime during failovers? Consider a setup that includes at least one primary and two secondary nodes, and explain how to configure read preferences for optimal performance while ensuring data consistency.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, Cody will suggest how you can approach replication to improve the availability of your database. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmj79p7m0fhfh0bzpn1kn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmj79p7m0fhfh0bzpn1kn.png" alt="Screenshot of Cody’s feedback" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After following Cody's instructions, click &lt;strong&gt;Apply&lt;/strong&gt; to add the code-related section to the file to be executed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftju5kmzstfijqceet7bp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftju5kmzstfijqceet7bp.png" alt="Screenshot showing the rest of the guide generated by Cody and the Apply button" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can even ask Cody to write the commands (in any of your preferred programming languages) that efficiently handle the Read or Write across the replicas.&lt;/p&gt;

&lt;p&gt;Overall, using AI tools like Cody is about making your MongoDB operations smoother and more effective—working alongside your expertise to overcome any challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;p&gt;By integrating AI into your development teams’ workflow, you can further improve your development process and create better solutions faster. It‘s not about replacing your MongoDB skills but amplifying them with the support of AI. &lt;br&gt;
With an AI tool like Cody, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adapt quickly to new challenges.&lt;/li&gt;
&lt;li&gt;Write efficient queries and improve operations.&lt;/li&gt;
&lt;li&gt;Enhance your database management skills.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, by combining your creativity and expertise with AI's vast knowledge, you can build better tools and deliver improved products to your customers.&lt;/p&gt;

&lt;p&gt;Ready to take the next step? &lt;a href="https://sourcegraph.com/cody" rel="noopener noreferrer"&gt;Sign up for Cody today&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwaredevelopment</category>
      <category>mongodb</category>
    </item>
    <item>
      <title>Quickly build UI components with AI</title>
      <dc:creator>Obisike Treasure</dc:creator>
      <pubDate>Tue, 17 Dec 2024 14:52:56 +0000</pubDate>
      <link>https://dev.to/hackmamba/quickly-build-ui-components-with-ai-d17</link>
      <guid>https://dev.to/hackmamba/quickly-build-ui-components-with-ai-d17</guid>
      <description>&lt;p&gt;Building UI components usually means writing a lot of code from scratch, fixing minor bugs, and working closely with designers to bring static designs to life. It’s always time-consuming, with you manually handling every detail, from layout to performance tweaks.&lt;/p&gt;

&lt;p&gt;AI is now changing how you can approach building UI elements. Instead of spending hours on repetitive tasks, you can use AI tools to quickly build and refine your UI components.&lt;/p&gt;

&lt;p&gt;In this guide, you’ll learn how to build and customize UI elements, create style guides, and develop more complex UIs using AI. By the end, you'll see how tools like &lt;a href="https://sourcegraph.com/cody" rel="noopener noreferrer"&gt;Cody&lt;/a&gt; reduce the time and effort involved in your UI development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along with this tutorial, you’ll need the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://code.visualstudio.com/download" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt; (VSCode)&lt;/li&gt;
&lt;li&gt;Fundamental knowledge of &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt; and &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/download/package-manager/current" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; installed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once these are in place, you'll need to set up the development environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the environment
&lt;/h2&gt;

&lt;p&gt;You’ll need to set up a React project, install Cody on your VSCode editor, and use Cody to configure TailwindCSS. This setup will serve as your development environment. Check out this &lt;a href="https://github.com/Otrex/cody-react" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; to see the full project you'll be building.&lt;/p&gt;

&lt;p&gt;Let’s start by creating the React project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating your React project
&lt;/h3&gt;

&lt;p&gt;To create your React project, open your terminal and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn create vite cody-react &lt;span class="nt"&gt;--template&lt;/span&gt; react-ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This command initializes a new React project with TypeScript, creating a project folder named &lt;code&gt;cody-react&lt;/code&gt; in your current directory.&lt;/p&gt;

&lt;p&gt;Next, open the project folder in your VSCode editor. Once it's open, you can proceed to install and configure Cody.&lt;/p&gt;
&lt;h3&gt;
  
  
  Steps to install and configure Cody
&lt;/h3&gt;

&lt;p&gt;To set up Cody on your VSCode editor, start by installing &lt;a href="https://marketplace.visualstudio.com/items?itemName=sourcegraph.cody-ai" rel="noopener noreferrer"&gt;Cody’s VSCode extension&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggasfb7ctjd1sq95032d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggasfb7ctjd1sq95032d.png" alt="Screenshot of the Cody’s extension on VSCode" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you’ll have to &lt;a href="https://sourcegraph.com/cody" rel="noopener noreferrer"&gt;sign up&lt;/a&gt; to be able to use Cody on your VSCode. Select your preferred sign-up method to continue and complete the account creation flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qrvlpwp1ft7edfeufnm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qrvlpwp1ft7edfeufnm.png" alt="Screenshot of the Sign in buttons on the Cody’s extension" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For additional information, you can refer to the &lt;a href="https://sourcegraph.com/docs/cody/clients/install-vscode" rel="noopener noreferrer"&gt;Cody documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To improve your workflow and avoid the need to rewrite prompts multiple times, utilize Cody's custom commands. This will allow you to apply the same prompts across all the components you create, saving you time and effort.&lt;/p&gt;

&lt;p&gt;Let's set up some of Cody's custom commands.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting up the Cody commands
&lt;/h3&gt;

&lt;p&gt;To create custom commands in your workspace, follow these steps:&lt;br&gt;
First, open the VS Code Command Palette by pressing &lt;strong&gt;Ctrl + Shift + P (Windows/Linux)&lt;/strong&gt; or &lt;strong&gt;Cmd + Shift + P (Mac)&lt;/strong&gt;. Type &lt;strong&gt;Cody Menu: Custom Commands&lt;/strong&gt; and select it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dci3m46tg6wgl2b58gc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dci3m46tg6wgl2b58gc.png" alt="Screenshot of the VSCode Command Pallete" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the Cody commands menu, select &lt;strong&gt;Custom Commands &amp;gt; New Custom Command&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bp9vxxnkm45wsi3g4c7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bp9vxxnkm45wsi3g4c7.png" alt="Screenshot of the New Custom Command selection" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter a descriptive name for your new custom command, such as &lt;strong&gt;ui-components-creator&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyislzm58xnh89f9wbnx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyislzm58xnh89f9wbnx.png" alt="Screenshot of the entering the name for your custom command" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, select the &lt;strong&gt;“ask”&lt;/strong&gt; mode since you’ll mostly be using the Cody chat.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabp49eyiqwswlmbzfdkp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabp49eyiqwswlmbzfdkp.png" alt="Screenshot of the section to select Ask mode" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, enter the instructions that Cody will use when executing the command.  You'll be creating two commands, and here are the detailed instructions for each:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For the &lt;strong&gt;ui-components-creator&lt;/strong&gt; command, use the following prompt:&lt;br&gt;
You are an expert in React+Tailwind+TS UI component design. Design the component. Note: Do not use template literals for tailwind classes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For the &lt;strong&gt;ui-components-customizer&lt;/strong&gt; command, use the following prompt:&lt;br&gt;
You are an expert in React+Tailwind+TS component design. Customize the component to follow the design system defined in the tailwind.config.js file, create variants based on sizes and colors, and also add things like the hover and active states. Note: Do not use template literals for tailwind classes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;For this project, the &lt;code&gt;ui-components-creator&lt;/code&gt; command will be used to generate the basic UI components, while the &lt;code&gt;ui-components-customizer&lt;/code&gt; command will be used to customize these components to align with the design system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7595piibvbpnnq72pnkf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7595piibvbpnnq72pnkf.png" alt="Screenshot of the section to enter the prompt" width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose one or more options for the context Cody should use to generate responses. This should include the &lt;strong&gt;Current File&lt;/strong&gt;, &lt;strong&gt;Selected Code&lt;/strong&gt;, and the &lt;strong&gt;Current Directory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcenb5lctokuqvxr4r77r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcenb5lctokuqvxr4r77r.png" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since you’re setting up the command for just this workspace, select the &lt;strong&gt;User Settings option&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk90vfdjxvf9pq02ibk7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk90vfdjxvf9pq02ibk7x.png" alt="Screenshot of the seection to save the cody command" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;Enter&lt;/code&gt; to finalize the creation of your custom command. For further information, you can refer to the &lt;a href="https://sourcegraph.com/docs/cody/capabilities/commands#custom-commands" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;;&lt;/p&gt;

&lt;p&gt;Here is how your custom commands should look in your VSCode workspace settings:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;.vscode/cody.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"ui-components-creator"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You are an expert in React+Tailwind+TS UI component design. Design the component. Note: Do not use template literals for tailwind classes."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"selection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"currentFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"currentDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ask"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ui-component-customizer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"You are an expert in React+Tailwind+TS component design. Customize the component to follow the design system defined in the tailwind.config.js file, create variants based on sizes and colors, and also add things like the hover and active states. Note: Do not use template literals for tailwind classes."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"selection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"currentFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"currentDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ask"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Next, let’s set up Tailwind CSS in your development environment.&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting up Tailwind CSS for your development environment
&lt;/h3&gt;

&lt;p&gt;To set up Tailwind CSS on the project, you'll need to install Tailwind CSS and its peer dependencies. This can be done by running the command.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; tailwindcss postcss autoprefixer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With the dependencies installed, generate the Tailwind configuration files. This is easily done by executing the command below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx tailwindcss init &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This command will create both &lt;code&gt;tailwind.config.js&lt;/code&gt; and &lt;code&gt;postcss.config.js&lt;/code&gt; files in your project.&lt;/p&gt;

&lt;p&gt;To ensure Tailwind can remove unused styles in production, open the &lt;code&gt;tailwind.config.js&lt;/code&gt; file and specify the paths to all your template files. Your configuration should look something like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/**/*.{js,jsx,ts,tsx}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Next, you need to add Tailwind’s directives to your CSS. Create a CSS file in the &lt;code&gt;src&lt;/code&gt; directory, for example, &lt;code&gt;src/index.css&lt;/code&gt;, and include the following directives:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Import this CSS file into your React application by adding &lt;code&gt;import './index.css';&lt;/code&gt; to your &lt;code&gt;src/index.js&lt;/code&gt; or &lt;code&gt;src/index.tsx&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;For more detailed information, you can refer to the &lt;a href="https://tailwindcss.com/docs/guides/vite" rel="noopener noreferrer"&gt;Tailwind CSS documentation&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Next, you’ll need to set up your Tailwind CSS theme configuration, which will serve as the design guide for your components. This configuration will include defining colors, padding, and other style properties. For this tutorial, we’ll be using the following color codes: &lt;code&gt;#00CBEC&lt;/code&gt;, &lt;code&gt;#A112FF&lt;/code&gt;, and &lt;code&gt;#FF5543&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Navigate to your &lt;code&gt;tailwind.config.json&lt;/code&gt; file. Use &lt;strong&gt;Opt + K&lt;/strong&gt; (or &lt;strong&gt;Alt + K&lt;/strong&gt; on Windows) to open Cody’s &lt;strong&gt;Edit Command&lt;/strong&gt; interface. Highlight all the content of the file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcED-LtK5piBpzz9St3_gQMM0cbMbEauWNvBARHOLh47_L5lwUYlTTPZEZo-aksHE-CE0KcGk7ZULzcG6-d5e63Cnz57LRmJhYazhf_X5Xyfc2iVTb98-tzVxQkJ-u6BjXK75vWQuTIpyrJ9Y2UOVL_Q8g%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcED-LtK5piBpzz9St3_gQMM0cbMbEauWNvBARHOLh47_L5lwUYlTTPZEZo-aksHE-CE0KcGk7ZULzcG6-d5e63Cnz57LRmJhYazhf_X5Xyfc2iVTb98-tzVxQkJ-u6BjXK75vWQuTIpyrJ9Y2UOVL_Q8g%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="The project’s existing Tailwind Configuration" width="1600" height="788"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, enter the following prompt:&lt;/p&gt;

&lt;p&gt;Update the Tailwind configuration to include the colors #00CBEC, #A112FF, and #FF5543, along with custom fonts, spacing, and other design systems elements like border-radius, box shadows, and breakpoints.&lt;/p&gt;

&lt;p&gt;Then click &lt;strong&gt;Submit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeaxC0TNo2Frj9gBwwOCt8XKlVN1fIRIjfafsDTGABMo9nZmEHUpLRrEwC9tKZ7DXT7sI4Ctvz2HHnak7TsCly-acvrNDnPZ-J621FDkDCX0PjhIN5e1zW8AciZVyt_0S8fJAdvYY6Lj0CC40krNDqRT90H%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeaxC0TNo2Frj9gBwwOCt8XKlVN1fIRIjfafsDTGABMo9nZmEHUpLRrEwC9tKZ7DXT7sI4Ctvz2HHnak7TsCly-acvrNDnPZ-J621FDkDCX0PjhIN5e1zW8AciZVyt_0S8fJAdvYY6Lj0CC40krNDqRT90H%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Addition of a prompt to Cody to edit the project’s tailwind.config file" width="1600" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, review and &lt;strong&gt;Accept&lt;/strong&gt; the changes proposed by Cody.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdyumDhJqdBfzyM7VxzHEZ6GbN49CaSag53cdgCXL9jpE2omdTMdmKlDBGRXDbQ6hGVYCDQ7rYTHRmoUz7Sp2HiDPGYYBpz4kpvU8Id1IteY54AmWDe15HfJ32CnzEvVmuWdM8a3ALe2czDUOcxaINRkXxE%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdyumDhJqdBfzyM7VxzHEZ6GbN49CaSag53cdgCXL9jpE2omdTMdmKlDBGRXDbQ6hGVYCDQ7rYTHRmoUz7Sp2HiDPGYYBpz4kpvU8Id1IteY54AmWDe15HfJ32CnzEvVmuWdM8a3ALe2czDUOcxaINRkXxE%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Accept generated code from Cody to edit the project’s tailwind.config file." width="1600" height="1010"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you’ve successfully set up tailwind on your project, let’s create the UI components.&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating basic UI components
&lt;/h2&gt;

&lt;p&gt;A good UI is built with components like buttons, switches, text inputs, progress bars, tabs, and many more. These elements are the core of a UI design system and shape the user experience.&lt;/p&gt;

&lt;p&gt;Traditionally, creating these components involves manually writing the code, which can be time-consuming, especially when handling multiple components. Cody simplifies this by generating code for a component directly within your project. &lt;/p&gt;

&lt;p&gt;You’ll build the following components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Button:&lt;/strong&gt; Allows users to perform actions by clicking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Switch:&lt;/strong&gt; This lets users toggle between different states.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text input:&lt;/strong&gt; Allows users to enter text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progress bar:&lt;/strong&gt; Shows the progress of an operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tabs:&lt;/strong&gt; Organizes high-level content.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To build these components with Cody, start by creating a dedicated &lt;code&gt;components&lt;/code&gt; directory. Then, create a &lt;code&gt;.tsx&lt;/code&gt; file for each component, such as &lt;code&gt;Switch.tsx&lt;/code&gt; or &lt;code&gt;TextInput.tsx&lt;/code&gt;. Let's begin by creating the button component.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating the button component
&lt;/h3&gt;

&lt;p&gt;Here’s how to create a button component with Cody:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: The steps for creating this button can be used to create other UI elements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After creating your &lt;strong&gt;Button.tsx&lt;/strong&gt; file, open a new Cody chat by right-clicking on the code editor, selecting the &lt;strong&gt;Cody&lt;/strong&gt; option from the menu, and choosing &lt;strong&gt;New Chat in Editor&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdsxKFCuNp1TZ-UVVjGzXo3E-y5I_epMoTJlyb7CoDysIVnboAa07cIm-Q7xRUnJ0fFH5h0uX6rFS7bGHt91KZn6i66eRxWlxyAvq1-WM-40c84A6VUgX87F8e895aPK0XWV6ktAa4czGvcpztnpg6UzeL8%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdsxKFCuNp1TZ-UVVjGzXo3E-y5I_epMoTJlyb7CoDysIVnboAa07cIm-Q7xRUnJ0fFH5h0uX6rFS7bGHt91KZn6i66eRxWlxyAvq1-WM-40c84A6VUgX87F8e895aPK0XWV6ktAa4czGvcpztnpg6UzeL8%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Cody chat right-click option." width="1600" height="855"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alternatively, you can click the &lt;strong&gt;Cody icon&lt;/strong&gt;. If an existing conversation is open, click &lt;strong&gt;New Chat&lt;/strong&gt; to start a new one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcpys904TCxWYKUi5j5liLCBk5EHMcvkYc93FkGUGVSRuSwgFKuiEVwKQ2z0Ezd0fdYeUv3RoWfbesshslFJ4vqaA0AHNQ6JGUYJeC5T4XrHwgAVmVaUCg5Z0qVWUwpLmNgcHvlPwnrCthWNVFHrhFOW54%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcpys904TCxWYKUi5j5liLCBk5EHMcvkYc93FkGUGVSRuSwgFKuiEVwKQ2z0Ezd0fdYeUv3RoWfbesshslFJ4vqaA0AHNQ6JGUYJeC5T4XrHwgAVmVaUCg5Z0qVWUwpLmNgcHvlPwnrCthWNVFHrhFOW54%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Cody's VS Code extension icon selection" width="1600" height="942"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click the &lt;strong&gt;Prompts&lt;/strong&gt; and select the &lt;strong&gt;ui-components-creator&lt;/strong&gt; option on the palette.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdOcAlnb1NE-onv0YcnQxDjdchzto77EidjBB45Q3-04XVCCMFoj5BpEwL5XsDYSMfZyTRKBFxePWVQzALgeQgXCgQwPlDjbFXQsGH-FniNEVNA_6Z-i0gDzCTq_nwK0MHQOnMOXUAuE_mN57ujVorsvg80%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdOcAlnb1NE-onv0YcnQxDjdchzto77EidjBB45Q3-04XVCCMFoj5BpEwL5XsDYSMfZyTRKBFxePWVQzALgeQgXCgQwPlDjbFXQsGH-FniNEVNA_6Z-i0gDzCTq_nwK0MHQOnMOXUAuE_mN57ujVorsvg80%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Cody's prompt selection" width="1600" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then click the play icon or press &lt;strong&gt;Enter.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfwZj9vnVObPLMWFkRxBjuaNyGq-AIzkUDSsp93y7VxpFNqPusLNdLF9gJRsL9C9N1ZyurYFuEGjg6yo8CrKmYZ-Iw4-nod82MNaer3qvTNRugcZm9o-8A-805Uv9rq3VIS6NEJJxUiXGasa8Q2uLZZJMse%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfwZj9vnVObPLMWFkRxBjuaNyGq-AIzkUDSsp93y7VxpFNqPusLNdLF9gJRsL9C9N1ZyurYFuEGjg6yo8CrKmYZ-Iw4-nod82MNaer3qvTNRugcZm9o-8A-805Uv9rq3VIS6NEJJxUiXGasa8Q2uLZZJMse%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Cody's play icon selection" width="1600" height="798"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cody will then generate the required code for the component, which you can review.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXckrcqBx_-UHPKDLdbycFUvbnLh-Zwge2ejek_7lUp-jfY05mP5ucC-YuMW3dBbPcThtINOIWiFx3IdtXpfFemMz4pH9mcPyYXoTWYPlmHBNN7x2qR3Wzto1ASiEjbMXGMmPVBz--ZjEAxqfTF_t6ViMXJm%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXckrcqBx_-UHPKDLdbycFUvbnLh-Zwge2ejek_7lUp-jfY05mP5ucC-YuMW3dBbPcThtINOIWiFx3IdtXpfFemMz4pH9mcPyYXoTWYPlmHBNN7x2qR3Wzto1ASiEjbMXGMmPVBz--ZjEAxqfTF_t6ViMXJm%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Cody's code generation" width="1600" height="1012"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click &lt;strong&gt;Apply&lt;/strong&gt; to add the code to the file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcogiE5BBKzOy-vY5uM1zjGHHoE3HIwZUp_oszsqWYMhrKz95RYeunWOx_lS2OQRDlTaVQQXqR9rAETqrYBqrNdVE-Ax7-qLIoBeiYXZJ97QcJxjxG5s4x_ABRKs19GGxphpdY0ZZiUxPj7RYw0lOjEoCs%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcogiE5BBKzOy-vY5uM1zjGHHoE3HIwZUp_oszsqWYMhrKz95RYeunWOx_lS2OQRDlTaVQQXqR9rAETqrYBqrNdVE-Ax7-qLIoBeiYXZJ97QcJxjxG5s4x_ABRKs19GGxphpdY0ZZiUxPj7RYw0lOjEoCs%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Apply Cody's generated code" width="1600" height="1004"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then click &lt;strong&gt;Accept&lt;/strong&gt; to accept the modifications made to the file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfSmN7f0wvcAF2EWFsDIzy07L7VNEwWg6Wl4LdnIhN1ocyx-KEIbbY9cYoG0qlDZG6X9yBfR3aNdxYMC7BM5iQ1Bo3vkGMdRphq1OlmQD1-cUnlRGyIf6DDn7YzET2mGiYcef9W6UdgbI46A8LpljgCg-E%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfSmN7f0wvcAF2EWFsDIzy07L7VNEwWg6Wl4LdnIhN1ocyx-KEIbbY9cYoG0qlDZG6X9yBfR3aNdxYMC7BM5iQ1Bo3vkGMdRphq1OlmQD1-cUnlRGyIf6DDn7YzET2mGiYcef9W6UdgbI46A8LpljgCg-E%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Accept Cody's generated code." width="1600" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the code generated by Cody:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Be sure to save the changes in the file.&lt;br&gt;
This is how the component would look.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfF8qHOofpcNMKoa7Dh9j-GaGvQq1zID4NOjFRbbbZAKPFrFMgyJ7qV3sWwkGM0RzRtQrx8rqZ_-j4nifN8ZY0ECOjlIAvepARSwL-0uFUWg49IOeLKGdFw3G8Y7Rur5osczeuF7qNGFVL_99TDM9EQzidF%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfF8qHOofpcNMKoa7Dh9j-GaGvQq1zID4NOjFRbbbZAKPFrFMgyJ7qV3sWwkGM0RzRtQrx8rqZ_-j4nifN8ZY0ECOjlIAvepARSwL-0uFUWg49IOeLKGdFw3G8Y7Rur5osczeuF7qNGFVL_99TDM9EQzidF%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the button component" width="1184" height="646"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  The switch component
&lt;/h3&gt;

&lt;p&gt;The switch component lets users toggle between different states on your website or your application. It's a straightforward way to turn features or settings on and off, with clear visual feedback showing the current state.&lt;br&gt;
Once you have created your &lt;code&gt;Switch.tsx&lt;/code&gt; component file, follow the same steps used when creating the button component.&lt;/p&gt;

&lt;p&gt;This is the react component code generated by Cody:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here is how the component is going to look.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcEx-M8xOfPx8CPx2812ffZqj9GMsWPGmUYa7x0Y8gZZMSPqDKds7qrOfAhvCASQyXIZcsEt5Kr_qmvAXCfPtO7hT3J6YrSxhDLitHiXky6TZqVKqgzeumNsfNSPqKPPlN_BYKDi2DDhKsVVELC3O0SrRc%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcEx-M8xOfPx8CPx2812ffZqj9GMsWPGmUYa7x0Y8gZZMSPqDKds7qrOfAhvCASQyXIZcsEt5Kr_qmvAXCfPtO7hT3J6YrSxhDLitHiXky6TZqVKqgzeumNsfNSPqKPPlN_BYKDi2DDhKsVVELC3O0SrRc%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the switch component" width="1366" height="652"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The text input component
&lt;/h3&gt;

&lt;p&gt;The text input component allows users to enter the text on a website or an application.&lt;br&gt;
In your created &lt;code&gt;TextInput.tsx&lt;/code&gt; component file, follow the steps illustrated in the first button component example. &lt;/p&gt;

&lt;p&gt;The generated code is as follows.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This is the input component designed by Cody.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXc7D0axS8Iy7NC5txmWvEpAgbP9Dak0683B5KWO4BTTIInARRJbvDMD1s2fmyyWAYmRy6xzJGr5plORuQkyqQftrApro4Fv_4DBujm8W2VTyKJdElMtVmMn2P1dCp9aQRNdovIDJl8IyMRMIvXJ_RfGdNRd%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXc7D0axS8Iy7NC5txmWvEpAgbP9Dak0683B5KWO4BTTIInARRJbvDMD1s2fmyyWAYmRy6xzJGr5plORuQkyqQftrApro4Fv_4DBujm8W2VTyKJdElMtVmMn2P1dCp9aQRNdovIDJl8IyMRMIvXJ_RfGdNRd%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the text input component" width="1600" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The progress bar component
&lt;/h3&gt;

&lt;p&gt;A progress bar component shows that the application has received a user's request and is moving closer to carrying out a requested action from that user.&lt;br&gt;
In the &lt;code&gt;ProgressBar.tsx&lt;/code&gt; you created, replicate the procedures shown in the initial button component example.&lt;/p&gt;

&lt;p&gt;See the code example generated by Cody: &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This generates the output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdy5JydwdgU-Rs-wYCQUbHTr1-QfxYwFNlHLp0UKTQopSNdbKz3UDfH88PMsCGoIsh_Owv9ux-Rbcmn4f0SCznumzfM5gzvT-tIl167bqrK30ZACzEx61RTVmlqm92-LGCITmkdiBDX3eAocdB6_Rh0ec0%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdy5JydwdgU-Rs-wYCQUbHTr1-QfxYwFNlHLp0UKTQopSNdbKz3UDfH88PMsCGoIsh_Owv9ux-Rbcmn4f0SCznumzfM5gzvT-tIl167bqrK30ZACzEx61RTVmlqm92-LGCITmkdiBDX3eAocdB6_Rh0ec0%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the progress bar component" width="1520" height="720"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The tabs component
&lt;/h3&gt;

&lt;p&gt;A tab component organizes high-level content in an application and supports switching between views, data sets, or functional aspects of the application.&lt;br&gt;
In your created &lt;code&gt;Tabs.tsx&lt;/code&gt; component file, apply the steps demonstrated in the button component example. &lt;/p&gt;

&lt;p&gt;Cody generates the following:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcsDej7x1ZruU-70lTuTBeWSuJwpNw6RLAtWqqtNybCzbLwi8ytsACU67Qm39OeLLRojpUds4w2X_ljueUq7nfJmCKns0ere_X8TdEycORwadlpsEtHFQW33pA7kekNFQLNHOwFXS3b2YdItNj-QHBnAFgO%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcsDej7x1ZruU-70lTuTBeWSuJwpNw6RLAtWqqtNybCzbLwi8ytsACU67Qm39OeLLRojpUds4w2X_ljueUq7nfJmCKns0ere_X8TdEycORwadlpsEtHFQW33pA7kekNFQLNHOwFXS3b2YdItNj-QHBnAFgO%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the Tabs component" width="1600" height="596"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing your UI components
&lt;/h2&gt;

&lt;p&gt;A consistent design enhances user experience. Customizing your components to follow a design pattern is crucial for achieving this consistency. Here's how to do it using Cody. &lt;/p&gt;

&lt;h3&gt;
  
  
  The button component
&lt;/h3&gt;

&lt;p&gt;A button component for a design system must have variants such as size and color. Let's get Cody to do this. Since you’ve created the prompt to handle the customization request, all you need to do is follow the following steps:&lt;/p&gt;

&lt;p&gt;First, open the &lt;code&gt;Button.tsx&lt;/code&gt; component file. Then, open a &lt;strong&gt;New Chat in Editor&lt;/strong&gt; by following the previously highlighted steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeKgD9XPgAkzWzgWdXf6SvJVzoYIX4k4wP_zeg54nFt873-3lomUmrTV4_GD6ZRTCmks7up2mJkB_7cpwEqUuXNycP6dqHa02C3wnymsqBk2FPnbmC0denf2r3FDSI_tt5ARSDHiXV48ckCayCwuw3n94_1%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeKgD9XPgAkzWzgWdXf6SvJVzoYIX4k4wP_zeg54nFt873-3lomUmrTV4_GD6ZRTCmks7up2mJkB_7cpwEqUuXNycP6dqHa02C3wnymsqBk2FPnbmC0denf2r3FDSI_tt5ARSDHiXV48ckCayCwuw3n94_1%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Cody chat" width="1600" height="780"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the chat field, type in &lt;strong&gt;@&lt;/strong&gt;. This brings out a list of files you can select from to add the file as context to your prompt. Select the &lt;strong&gt;tailwind.config.js&lt;/strong&gt; file. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeg_1XLOOeGfMKpu1vP52wA7YZ3O1pZIPA4qMG6RPSLXyo05WFXCjkUZs4djs2CisnzOTpgpK15cevLiqYnChamcVAZv-JbHG2DWxSPei7DjWdgwnkaRAxkIpnZOFD8dX9YZB8556fSXYCLLFCkHhWfI9E%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeg_1XLOOeGfMKpu1vP52wA7YZ3O1pZIPA4qMG6RPSLXyo05WFXCjkUZs4djs2CisnzOTpgpK15cevLiqYnChamcVAZv-JbHG2DWxSPei7DjWdgwnkaRAxkIpnZOFD8dX9YZB8556fSXYCLLFCkHhWfI9E%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Selecting the tailwind config using the @ command" width="1600" height="809"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click &lt;strong&gt;Prompts&lt;/strong&gt; and select the &lt;strong&gt;ui-components-customizer&lt;/strong&gt; option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdOB1dgwXci_G2gCt8KMtJS3VkLeWO_5-UpAfQyVzEp0yaVTeKM6ir5fIxucSRXDEU2Gi6lI_jU-tiaVb_6GYeUqD41eD966QpFK20UZAzQgzUPJq5TuCKavIk9RH7zW0AQEibeKEas91UoPtIPY3274hd3%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdOB1dgwXci_G2gCt8KMtJS3VkLeWO_5-UpAfQyVzEp0yaVTeKM6ir5fIxucSRXDEU2Gi6lI_jU-tiaVb_6GYeUqD41eD966QpFK20UZAzQgzUPJq5TuCKavIk9RH7zW0AQEibeKEas91UoPtIPY3274hd3%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Selecting the ui-component-customizer command" width="1600" height="789"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then press &lt;strong&gt;Enter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeTywzRPpsiLq-ghdpyIjk-j-9pE346K3q3Cv9EihdjGyTpEZSJR9ixh3muCP2Dsm92rGwq-APmFa9Lu3HC5l9P8RogVbzY-oH_NEJJphRCk7EWeWtjuBsGOhW0lLtaQA58tHsm-aS5aUnB4OTLF5C5yNpv%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeTywzRPpsiLq-ghdpyIjk-j-9pE346K3q3Cv9EihdjGyTpEZSJR9ixh3muCP2Dsm92rGwq-APmFa9Lu3HC5l9P8RogVbzY-oH_NEJJphRCk7EWeWtjuBsGOhW0lLtaQA58tHsm-aS5aUnB4OTLF5C5yNpv%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Code generated by the ui-component-customizer command" width="1600" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Review the generated code, apply the changes, and accept them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdQv6XT6Xu55bGTybnmczR1pGHyz-JI0B_j0PCphDiPE9LbqbyhUNJ0-Z34P4GEL09Y2RDbmsukDdoSStB4I0CKJhHoiSXUy2a4alZgpU1vqqQG8cKSxsGL7ja7QmoZJJnjcWM5HvaTwZ_9cdRTcqya4VdS%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdQv6XT6Xu55bGTybnmczR1pGHyz-JI0B_j0PCphDiPE9LbqbyhUNJ0-Z34P4GEL09Y2RDbmsukDdoSStB4I0CKJhHoiSXUy2a4alZgpU1vqqQG8cKSxsGL7ja7QmoZJJnjcWM5HvaTwZ_9cdRTcqya4VdS%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Accepting generated code" width="1600" height="833"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: You can choose to accept some of the changes, depending on what you want.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is the final code update for the button.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This is how the button looks afterward.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfKTnrMBvMOxgLkKw7fkZtkSj7k5vskoipo7PK9eNLeEte0v4YDxx49fYTdxqnyagxSR56Ca2qWIRQf4gBLMuB8FJ7HUNz24zB5ZGZqOw6elVrFkFSOWz7BFb0tfOjKL4ncBiZOd6FoqtbY4IIWX-nEIz14%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfKTnrMBvMOxgLkKw7fkZtkSj7k5vskoipo7PK9eNLeEte0v4YDxx49fYTdxqnyagxSR56Ca2qWIRQf4gBLMuB8FJ7HUNz24zB5ZGZqOw6elVrFkFSOWz7BFb0tfOjKL4ncBiZOd6FoqtbY4IIWX-nEIz14%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the button component with the design system" width="1264" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Customizing the switch component
&lt;/h3&gt;

&lt;p&gt;To customize the switch component, first, open the &lt;code&gt;Switch.tsx&lt;/code&gt; file so Cody can add it to its prompt context. Then, start a new chat by following the same steps you used earlier when customizing the buttons.&lt;br&gt;
Just like with the button customization, add the tailwind.config.js file to the chat's context, then select the ui-component-customizer command from the prompts. &lt;br&gt;
Cody will generate this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Here is the final look of the switch component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXd4AIgM_JIC5jki2IgUnKwxKu9Kyu-fCK0D7o4ZcgfxDH21hofJ4fo5nKblHZXCNBtjh1zc7YKmUffl0qyH6LKs7tjrrlIe7_FVraE0UhawaqSzBvKCSfzQSEAsQMLtZF5HwTgb8FA0IT-gvFlE0IfyeMpF%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXd4AIgM_JIC5jki2IgUnKwxKu9Kyu-fCK0D7o4ZcgfxDH21hofJ4fo5nKblHZXCNBtjh1zc7YKmUffl0qyH6LKs7tjrrlIe7_FVraE0UhawaqSzBvKCSfzQSEAsQMLtZF5HwTgb8FA0IT-gvFlE0IfyeMpF%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the switch component with the design system" width="1196" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Customizing the text input component
&lt;/h3&gt;

&lt;p&gt;Similar to the switch component, follow the steps used in customizing the component, then apply and accept the changes from Cody.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXf621ju3qw-InzaAm7UBPuggKEYnYTBTCOIKcztfia_Qax7bhHCayl9LzNOaRq69uaDZVafp0sH7kHAhEk0qX4--yAVcnTu_NsiBZBg6j1603F5Ikh_qLS5ag-blWQK-egKobBLgjv4ei_23rJl449li3b9%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXf621ju3qw-InzaAm7UBPuggKEYnYTBTCOIKcztfia_Qax7bhHCayl9LzNOaRq69uaDZVafp0sH7kHAhEk0qX4--yAVcnTu_NsiBZBg6j1603F5Ikh_qLS5ag-blWQK-egKobBLgjv4ei_23rJl449li3b9%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Generated TextInput component code from Cody" width="1600" height="888"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After applying and accepting the code changes, you’ll notice that on line 3, there is a typescript error. You can use Cody to rectify this.&lt;/p&gt;

&lt;p&gt;To do this, hover over the underlined error to display the menu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXerxzUTTpwEfDHK12hqYXUiVjnObUd4ZiMQNFFvGF2vqNlIs2gon0Rlb39AUyZwzM5RBmWulalIPOETARH__r9r-9xnaRGhfddVzkvPrmulo727qRBSZBb6DO4Ss4VK4AkHU_LUTULKjhXT-oTE6PMA3_IK%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXerxzUTTpwEfDHK12hqYXUiVjnObUd4ZiMQNFFvGF2vqNlIs2gon0Rlb39AUyZwzM5RBmWulalIPOETARH__r9r-9xnaRGhfddVzkvPrmulo727qRBSZBb6DO4Ss4VK4AkHU_LUTULKjhXT-oTE6PMA3_IK%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Display of errors in the generated TextInput component code from Cody" width="1600" height="775"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click &lt;strong&gt;Quick Fix.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXetVN9QfcDNjyphsRIvVqz8-utC4o0KYZJe5oCJbOyDlneBz2U0uzRIwM3CcpqrYv3B9foCSq6YolsP_JxiFZlleEF_hRQhexjJ5ULXM69ZziGkEzT3EkG8c3_hDwxkHH4Gte29fRK6hHJJ0Q4RN2lm2vvB%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXetVN9QfcDNjyphsRIvVqz8-utC4o0KYZJe5oCJbOyDlneBz2U0uzRIwM3CcpqrYv3B9foCSq6YolsP_JxiFZlleEF_hRQhexjJ5ULXM69ZziGkEzT3EkG8c3_hDwxkHH4Gte29fRK6hHJJ0Q4RN2lm2vvB%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Selecting the Quick Fix option in the generated TextInput component code" width="1308" height="674"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then click &lt;strong&gt;Ask Cody to Fix.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdlsNLL2YODH4bIvIf2iLOZY84Yrv7CTsGApb62QxkahQ6pArS3rkdRfXlAdjjBWujokpV2boPwAKcbIhI7twrvYZ-quMSLcbO6S__szrkXWDg2Mfcn-r3Cksilso4izewi9mC5QYzP19L_K1SOl52_l9o%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdlsNLL2YODH4bIvIf2iLOZY84Yrv7CTsGApb62QxkahQ6pArS3rkdRfXlAdjjBWujokpV2boPwAKcbIhI7twrvYZ-quMSLcbO6S__szrkXWDg2Mfcn-r3Cksilso4izewi9mC5QYzP19L_K1SOl52_l9o%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Selecting the Ask Cody to Fix option in the generated TextInput component code" width="1600" height="708"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once that is completed, accept the changes Cody suggested. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfGT93DuZE4hGnL6mn8vOb1L4J9Y9cVZSajcobRi2h3SP5sboQLKaZnogfwm56qZbUF0xlC1cKq4VzhNYTkMaCmZ58xSulZTL-Zcg3m8XG79SjzKMOVISb9krlRBzZmbod-oA2UhaJaFa5psXP2agOMa3nF%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfGT93DuZE4hGnL6mn8vOb1L4J9Y9cVZSajcobRi2h3SP5sboQLKaZnogfwm56qZbUF0xlC1cKq4VzhNYTkMaCmZ58xSulZTL-Zcg3m8XG79SjzKMOVISb9krlRBzZmbod-oA2UhaJaFa5psXP2agOMa3nF%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Accepting the Cody Fix option in the generated TextInput component code" width="1600" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the final result.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Also, here is the final output of the modifications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXd0-m-boOpl2MUT6tfAeFA_5ISBNrhOvF1cy4SxKXmiXziPUhTZ5av2cHvYSTqk0Guv4yW_tVTwQRT7yogNu-FYVJia1XE-U1Rt11aNIHBCjawM84cqLGSuCNgu064hhZRworgeAI5KbuLoP90Pvnws5xKF%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXd0-m-boOpl2MUT6tfAeFA_5ISBNrhOvF1cy4SxKXmiXziPUhTZ5av2cHvYSTqk0Guv4yW_tVTwQRT7yogNu-FYVJia1XE-U1Rt11aNIHBCjawM84cqLGSuCNgu064hhZRworgeAI5KbuLoP90Pvnws5xKF%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the input component with the design system" width="1130" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can repeat similar steps for &lt;strong&gt;the Progress Bar&lt;/strong&gt; and the &lt;strong&gt;Tabs&lt;/strong&gt; components.&lt;br&gt;
Here is the progress bar customized look.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfqPJhpx9D7QL8nwaqvrGWchQPNJMuRsIcVku9s0eiLWL9juhFQFJhUzshetjl-oDJ0FfNeHMVnEOrfiKsuIAKEQ9JMI9IMrGMa5oD66GUA6VoKAQo3az6PtpzySeb5iudCmYRwVr1Ul1VzFvTSRur5l4qo%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfqPJhpx9D7QL8nwaqvrGWchQPNJMuRsIcVku9s0eiLWL9juhFQFJhUzshetjl-oDJ0FfNeHMVnEOrfiKsuIAKEQ9JMI9IMrGMa5oD66GUA6VoKAQo3az6PtpzySeb5iudCmYRwVr1Ul1VzFvTSRur5l4qo%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the progress bar component with the design system" width="1210" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here is the new tab component. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXe5AYKhYfG9Dj3RObPILK3p5iYLU0crCsEjwYW32aagUCJJI0znU1PaqfprO4Elby--74WPkltnpHClLDCV9AFZ-tju_xCCyeN0gjNcj_fuJCEfhmgDGepuq1Omrn3EWYCHfRLXrgvc1iLPZ8hcnQP8O4WU%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXe5AYKhYfG9Dj3RObPILK3p5iYLU0crCsEjwYW32aagUCJJI0znU1PaqfprO4Elby--74WPkltnpHClLDCV9AFZ-tju_xCCyeN0gjNcj_fuJCEfhmgDGepuq1Omrn3EWYCHfRLXrgvc1iLPZ8hcnQP8O4WU%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the tab component with the design system." width="1480" height="724"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Building complex UI component systems
&lt;/h2&gt;

&lt;p&gt;Now that you’ve generated the basic UI components and customized them to match your design system, you can combine these components to create a complete user interface. You can achieve this by referencing the components via their files using the @ key within your prompt.&lt;/p&gt;

&lt;p&gt;To demonstrate, let’s create a login and register UI using all the components you created.&lt;br&gt;
Navigate to your &lt;code&gt;App.tsx&lt;/code&gt; file and open a new chat in the editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeDf7-m1FI3HLHclNTTcwJVIn3ojsuHjI_dxEoATcFj2U79bGYOIgBHQbSaNfRWNaC5ZcbYZnlKZIPVFrzwQ4I3Cs00ugFicOHLp13xZpXbHFtM_OAsERTLpZKiVwGUtVAFSKhYEqavy8qmydd79o6kHs-p%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeDf7-m1FI3HLHclNTTcwJVIn3ojsuHjI_dxEoATcFj2U79bGYOIgBHQbSaNfRWNaC5ZcbYZnlKZIPVFrzwQ4I3Cs00ugFicOHLp13xZpXbHFtM_OAsERTLpZKiVwGUtVAFSKhYEqavy8qmydd79o6kHs-p%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Cody chat referencing the App.tsx file." width="1600" height="839"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, add all your component files and the &lt;strong&gt;tailwind.config.json&lt;/strong&gt; file in the chat section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdJlHYEP3Smh7OniZa1zyRvjals8XXfDOrGfogLAKCs8NlBuVQw-GIikEgnPr75fxGLPcDII_0NRsPCxPA6XLx5ccvYXpk9ZfFWWoHKOr4u9bgAjdc6h0AI5pOdSBFNCbezjXEWHYfLTJ8GX_S9Yzigr88%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdJlHYEP3Smh7OniZa1zyRvjals8XXfDOrGfogLAKCs8NlBuVQw-GIikEgnPr75fxGLPcDII_0NRsPCxPA6XLx5ccvYXpk9ZfFWWoHKOr4u9bgAjdc6h0AI5pOdSBFNCbezjXEWHYfLTJ8GX_S9Yzigr88%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Cody chats with the component files added to the Cody’s context." width="1600" height="659"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then add the following prompt:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are an expert in designing UI pages. You are good with react+tailwind+ts. Use the components and images from free sources like Unsplash to design a login and register UI. The login and register should be separate using the Tabs and the progress bar should calibrate when the form is being filled. Once a form field is filled out, the progress should be increased on the progress bar, and the terms and conditions should switch, too.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Next, apply the changes to your &lt;code&gt;App.tsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcvBmicLxVsHbdA_pWtzdpiV570unBMn7E6yBtEVMZMBtvdPV2B6FceqN46GOZlUrfhaEHIW1d6ZOibXiEntRtdZzMKfBqKGn1d6bNZ38n4WZhwBLHh9bnjoSIvwq6FXpEw6hBiyD4iJK2P_jKnaT2Kf0Ip%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcvBmicLxVsHbdA_pWtzdpiV570unBMn7E6yBtEVMZMBtvdPV2B6FceqN46GOZlUrfhaEHIW1d6ZOibXiEntRtdZzMKfBqKGn1d6bNZ38n4WZhwBLHh9bnjoSIvwq6FXpEw6hBiyD4iJK2P_jKnaT2Kf0Ip%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Cody's chat prompt for generating a login and register UI." width="1600" height="1021"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After applying and accepting the changes, save the file, and then on your terminal, run the following command to start your application.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This starts the react development server at localhost.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcjZd3zWEKwrAMC5TNDT75LDsT5lTudrkPPIheHEoXTM_m_2kRnYsawaJDBh2W--2kd3K966hHK-JBfNhChJDTEVrfnaJfXt1Sbl9lK7f0WVWlHwioaOuzsV-TNgSHTjO5HWzkhzKwbmgrYnqRrU8lFKL3e%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcjZd3zWEKwrAMC5TNDT75LDsT5lTudrkPPIheHEoXTM_m_2kRnYsawaJDBh2W--2kd3K966hHK-JBfNhChJDTEVrfnaJfXt1Sbl9lK7f0WVWlHwioaOuzsV-TNgSHTjO5HWzkhzKwbmgrYnqRrU8lFKL3e%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="View of the Login and Register components." width="1600" height="962"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the image is broken. You can use Cody to fix it.&lt;br&gt;
Navigate to the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag on the &lt;code&gt;App.tsx&lt;/code&gt; file and highlight it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfhXRNvhOrZBNCZOOxbCS-PcaxcxnaMu3YU03j21zySYJck40i_RUj9wgHoJPD9vyr_skn9fU7V1RYL5wVmm1UZIYVvw-Wc9nfLLDy8Yg536I8IPwLCOY0AVqHgbBR6ILjfVNacC5kVXzl47SG4_N0C1EPO%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXfhXRNvhOrZBNCZOOxbCS-PcaxcxnaMu3YU03j21zySYJck40i_RUj9wgHoJPD9vyr_skn9fU7V1RYL5wVmm1UZIYVvw-Wc9nfLLDy8Yg536I8IPwLCOY0AVqHgbBR6ILjfVNacC5kVXzl47SG4_N0C1EPO%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Selecting the &amp;lt;img/&amp;gt; tag in the generated code." width="1600" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the &lt;strong&gt;Opt + K&lt;/strong&gt;  command (on Mac) or the &lt;strong&gt;Alt + K&lt;/strong&gt; command (on Windows) to bring out Cody’s &lt;strong&gt;Edit Code&lt;/strong&gt; interface. Then, enter the following prompt.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Replace the src with "https://images.pexels.com/photos/27582545/pexels-photo-27582545/free-photo-of-neon-lights.jpeg"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Next, accept and save the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcZNn9sRwlltyWhybs6HONRUniD13dh0aRspng0hV_s-rAv2_kfNB0sEfAQY6D7aUXTaEDCMa-Vr-SBQvYii7zxIQD7CIRgwFTrE99hMkP-17a8Lj9Xwr25fi2PAEG77nA2RPEGH1iMTSZ3BxfIbuSnZqSg%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcZNn9sRwlltyWhybs6HONRUniD13dh0aRspng0hV_s-rAv2_kfNB0sEfAQY6D7aUXTaEDCMa-Vr-SBQvYii7zxIQD7CIRgwFTrE99hMkP-17a8Lj9Xwr25fi2PAEG77nA2RPEGH1iMTSZ3BxfIbuSnZqSg%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Replacing the image on the generated code" width="1600" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the final code generated by Cody.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This is how the page looks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcK0mHIhpuTBEFuqtD2rvscGU86Phl9bBVR4zLbwidnNdVcYtujXzqUsRJI1wz6CTQ3rqnXsbjH5NugZstrsgFCFL5XMaA5rPqufCOYeUkf2qoR8bI12LK2NTs_cgSgdZ_FGqmvOK8PdbxOZhqK4g2o7cdy%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcK0mHIhpuTBEFuqtD2rvscGU86Phl9bBVR4zLbwidnNdVcYtujXzqUsRJI1wz6CTQ3rqnXsbjH5NugZstrsgFCFL5XMaA5rPqufCOYeUkf2qoR8bI12LK2NTs_cgSgdZ_FGqmvOK8PdbxOZhqK4g2o7cdy%3Fkey%3DMOo-btjrqLzUyz1bs8lz_g" alt="Final View of the Login Screen" width="1600" height="1062"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Watch the video to see the Login and Register screen designed by Cody using the components.&lt;/p&gt;


&lt;div&gt;
  &lt;iframe src="https://loom.com/embed/30fc974639fe4a50aefaa1aa3f71c3d7"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;


&lt;p&gt;Now that you have completed the UI, you can enhance it further by adding more context to your prompt to specify how you want your UI to look. Feel free to experiment with different prompts that you come up with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;Throughout this article, you've seen how Cody can transform how you build UI components, from basic buttons to complex, dynamic systems. Cody handles the heavy lifting so you can focus on crafting good UI/UX designs. Whether you’re customizing components or managing complex UI systems, Cody provides the tools to make the process faster and more efficient.&lt;/p&gt;

&lt;p&gt;Now, it's your turn to put these capabilities into practice. Here are a few ideas to get you started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;E-commerce product page:&lt;/strong&gt; Create a responsive product page with a carousel, product details, and an "&lt;strong&gt;Add to Cart&lt;/strong&gt;" button.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard interface:&lt;/strong&gt; Build a dashboard with interactive charts, data tables, and navigation tabs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Form validation:&lt;/strong&gt; Design a multi-step form with real-time validation and progress indicators.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Landing page:&lt;/strong&gt; Develop a landing page with a hero section, feature highlights, and a call-to-action button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Experiment with these projects and see how Cody can assist you in building faster and improving your development workflow. &lt;a href="https://sourcegraph.com/cody" rel="noopener noreferrer"&gt;Sign up&lt;/a&gt; &lt;a href="https://sourcegraph.com/cody" rel="noopener noreferrer"&gt;now&lt;/a&gt; to build UIs faster with Cody.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>ai</category>
      <category>react</category>
    </item>
    <item>
      <title>How to collect marketing campaign email leads with Mailgun and Appwrite in minutes</title>
      <dc:creator>Obisike Treasure</dc:creator>
      <pubDate>Mon, 08 Jan 2024 16:22:31 +0000</pubDate>
      <link>https://dev.to/hackmamba/how-to-collect-marketing-campaign-email-leads-with-mailgun-and-appwrite-in-minutes-83g</link>
      <guid>https://dev.to/hackmamba/how-to-collect-marketing-campaign-email-leads-with-mailgun-and-appwrite-in-minutes-83g</guid>
      <description>&lt;p&gt;Collecting marketing campaign email leads is fundamental to modern digital marketing strategies. It systematically gathers contact information, primarily email addresses, from individuals interested in a brand's products, services, or content.&lt;/p&gt;

&lt;p&gt;This process is crucial for building and maintaining an email marketing list, a valuable tool for organizations to establish and nurture connections with their audience.&lt;/p&gt;

&lt;p&gt;Various methods can be employed to collect email leads, such as utilizing web opt-in forms on websites and incorporating incentives like discounts or exclusive content. Web surveys, content or product upgrades, and online events like webinars or virtual summits can also capture email addresses during audience participation.&lt;/p&gt;

&lt;p&gt;One of the significant challenges businesses face while setting up the collection of their email leads is the choice of technology. This choice can affect the speed at which organizations set up their campaign, the effectiveness of managing the email list, and the integration with their other existing platforms. This is where Appwrite, through &lt;a href="https://appwrite.io/docs/products/functions?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Appwrite Functions&lt;/a&gt; and &lt;a href="https://www.mailgun.com/?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Mailgun&lt;/a&gt; — a powerful email service provider — comes in.  &lt;/p&gt;

&lt;p&gt;Appwrite provides ready-made function templates that allow businesses to set up applications easily. One of these templates is the &lt;strong&gt;email contact form&lt;/strong&gt;. The email contact form template is designed to help gather email leads for marketing campaigns. It also includes a prebuilt contact form user interface that businesses can customize to meet their specific needs.&lt;/p&gt;

&lt;p&gt;This tutorial demonstrates how you can set up the email leads collection system on your Next.js website using the email contact form provided by Appwrite and the Mailgun email service provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To follow along comfortably with this tutorial, you’ll need a few things: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic web development knowledge and a basic understanding of Next.js.&lt;/li&gt;
&lt;li&gt;An active &lt;a href="https://cloud.appwrite.io/register?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Appwrite cloud account&lt;/a&gt; and a &lt;a href="https://signup.mailgun.com/new/signup?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Mailgun account&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A code editor or Integrated Development Environment (IDE), preferably VScode.&lt;/li&gt;
&lt;li&gt;Basic knowledge of Git, a &lt;a href="https://github.com/signup" rel="noopener noreferrer"&gt;GitHub account&lt;/a&gt;, and a repository on that account.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en/download/current" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; installed.&lt;/li&gt;
&lt;li&gt;A CLI terminal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Repository
&lt;/h2&gt;

&lt;p&gt;In case you want to view the repository of the entire Next.js leads collection website, check out this &lt;a href="https://github.com/Otrex/hackmamba-appwrite-nextjs-leads-page?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Mailgun
&lt;/h2&gt;

&lt;p&gt;To initiate email communications through Mailgun, you must retrieve the Simple Mail Transfer Protocol (SMTP) keys that Appwrite requires for sending emails through Mailgun.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this tutorial, you'll be using the sandbox environment. For instructions on using the live environment, refer to the detailed &lt;a href="https://documentation.mailgun.com/en/latest/user_manual.html#verifying-your-domain" rel="noopener noreferrer"&gt;guidelines&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Retrieving the SMTP keys&lt;/strong&gt;&lt;br&gt;
To perform this task, go to your Mailgun account dashboard. Once there, locate and click on the &lt;strong&gt;Sending&lt;/strong&gt; menu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FY1NqJ_88Fdy7Q9LrQec1pepN8lDqvUVMYyG2vM0tK3PqQpASQkilgWPPtbtq9SzNmZwmF3dEFsJeJwYfIgVO87AcsgwyPRbM3mFGJ74nZKPATk2KE0vDUjV0SCxhlMFIAA6xa6x-KE4Oqh416u40E9k" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FY1NqJ_88Fdy7Q9LrQec1pepN8lDqvUVMYyG2vM0tK3PqQpASQkilgWPPtbtq9SzNmZwmF3dEFsJeJwYfIgVO87AcsgwyPRbM3mFGJ74nZKPATk2KE0vDUjV0SCxhlMFIAA6xa6x-KE4Oqh416u40E9k" alt="The sending menu on the Mailgun dashboard" width="1600" height="843"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, select &lt;strong&gt;Overview.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2F1XpcrNC7RA3X_x4AbwaNKS2TvdajCr3yQG37FV6C8XTtk1VQozZRfUlznKbye_SKFssg8Hp4m-0Qdc7cvcBksGC4YiMMTwaQ58IQY6PAs00Du7qM8kSSREQa0aPqjFUFK-45iVW6crlxxe-g-QcKzRI" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2F1XpcrNC7RA3X_x4AbwaNKS2TvdajCr3yQG37FV6C8XTtk1VQozZRfUlznKbye_SKFssg8Hp4m-0Qdc7cvcBksGC4YiMMTwaQ58IQY6PAs00Du7qM8kSSREQa0aPqjFUFK-45iVW6crlxxe-g-QcKzRI" alt="The overview option" width="1600" height="847"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Afterward, navigate to the &lt;strong&gt;SMTP&lt;/strong&gt; section and click &lt;strong&gt;Select&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2Fuox08K6u-cBl47Nh0Aq395GKk4GNs1Ia5Y-UrwPGa_DUIvPMW5144a84xen7rMRiI7fbkwQ3c4rEErLE2odcFxBhJlMEpXGPldbJFjAhW_LH-a5-Y_azuHw_1VrfV3pBvRtvAPAFyg-WdmnAb-r7bKQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2Fuox08K6u-cBl47Nh0Aq395GKk4GNs1Ia5Y-UrwPGa_DUIvPMW5144a84xen7rMRiI7fbkwQ3c4rEErLE2odcFxBhJlMEpXGPldbJFjAhW_LH-a5-Y_azuHw_1VrfV3pBvRtvAPAFyg-WdmnAb-r7bKQ" alt="The screenshot showing the Select button" width="1600" height="847"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once complete, you can retrieve the SMTP credentials from the section shown below. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FyQprq3vrai_V3Kdd1HLREZRLOzO-fm_8Lxgg8iRws-EpU0o2x3ooaaFiHviEBhfsxujgxrAauZ7QoeBArLCmKtVhE7Uebpq1au9ExtK-LlVm4aUhc4f0gILW65t2l_9C8W3PlInywSzTgudqoV7x7zQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FyQprq3vrai_V3Kdd1HLREZRLOzO-fm_8Lxgg8iRws-EpU0o2x3ooaaFiHviEBhfsxujgxrAauZ7QoeBArLCmKtVhE7Uebpq1au9ExtK-LlVm4aUhc4f0gILW65t2l_9C8W3PlInywSzTgudqoV7x7zQ" alt="The screenshot showing the SMTP credentials on Mailgun" width="1600" height="846"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuring Appwrite
&lt;/h2&gt;

&lt;p&gt;To proceed with the configuration, navigate to your Appwrite Cloud account dashboard, create a new project by entering the desired project name, and click &lt;strong&gt;Create project,&lt;/strong&gt; as indicated below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2F0NeRH8dKVbvp7z_52z8M5XVDxMdEJcNJ2WltXANhPCF7k6TN56Mj9ZcpmygYrfebMIKnzh53wp7f1ACMuZOT5tOScOFohcSEcj8AJ-tFR-1kGoixdG3PviOzDbtvirfLNoXBFnoPw_klscha5x4m9-s" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2F0NeRH8dKVbvp7z_52z8M5XVDxMdEJcNJ2WltXANhPCF7k6TN56Mj9ZcpmygYrfebMIKnzh53wp7f1ACMuZOT5tOScOFohcSEcj8AJ-tFR-1kGoixdG3PviOzDbtvirfLNoXBFnoPw_klscha5x4m9-s" alt="A screenshot showing the create a new project on Appwrite" width="1600" height="919"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, click on the &lt;strong&gt;Functions&lt;/strong&gt; menu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FrMoMdRT-PqtJvOR-oyk5dqlMbQ7T8J1SAubC84XUkngvIqsdZOn1QXBWawnvUQ_QqgYdBtm9gD3o_-fhhiJFlutfCX2vMBgDhyvtnu7crQQh1DXFdl1lsxtcglS1kVveya6ZwqcYP_Au1mfRgKeF9O0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FrMoMdRT-PqtJvOR-oyk5dqlMbQ7T8J1SAubC84XUkngvIqsdZOn1QXBWawnvUQ_QqgYdBtm9gD3o_-fhhiJFlutfCX2vMBgDhyvtnu7crQQh1DXFdl1lsxtcglS1kVveya6ZwqcYP_Au1mfRgKeF9O0" alt="A screenshot showing the Functions menu" width="1600" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click the &lt;strong&gt;templates&lt;/strong&gt; tab to view the available templates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2Fuu7KaeZq9FcGks6qJArDNfx82T7X2Ra7qv5EJKyHwURE2Oum2ZzJzGutxW1ymU076I19WCuesGXHcOh_HGO7yra4zssXHzqNvIKTh63gwhf0XZQwepbHw4vWA5Z3pCp_RRSQHymaeDX7haonsnII3HI" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2Fuu7KaeZq9FcGks6qJArDNfx82T7X2Ra7qv5EJKyHwURE2Oum2ZzJzGutxW1ymU076I19WCuesGXHcOh_HGO7yra4zssXHzqNvIKTh63gwhf0XZQwepbHw4vWA5Z3pCp_RRSQHymaeDX7haonsnII3HI" alt="A screenshot showing the Templates tab menu button" width="1600" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the search field, enter &lt;strong&gt;email contact form&lt;/strong&gt; to search for the template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FrN9-cgWXD9hDFXH-7yueo5iXUay02lJlLJOd-3PHrW6lty76b5BL8hzwVwWjxINYCCyiKge56AqyYxdXAv6biy-0W36_Lal2Duxf78waXkheUbmp90C_APggR_PC_prtAw2fOi4qItw2tdaSNAxAcCA" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FrN9-cgWXD9hDFXH-7yueo5iXUay02lJlLJOd-3PHrW6lty76b5BL8hzwVwWjxINYCCyiKge56AqyYxdXAv6biy-0W36_Lal2Duxf78waXkheUbmp90C_APggR_PC_prtAw2fOi4qItw2tdaSNAxAcCA" alt="A screenshot showing the template searching action" width="1600" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Afterward, click &lt;strong&gt;Create function&lt;/strong&gt; to initiate the setup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FyH8IcSi_2q4TCpBpe2x4ZC12QyO1XP41DqvUrPu3rZNkFpYIvRnxJ5ebVm1gLUVAApWjvyhtzcpR5QIHYVTMukXX4u4qTZ8X5QMGz8oF7L9W68W3Fi8pN_gXgMZg-yO4MLK5Wp4nuJfZi0jW_R5thXo" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FyH8IcSi_2q4TCpBpe2x4ZC12QyO1XP41DqvUrPu3rZNkFpYIvRnxJ5ebVm1gLUVAApWjvyhtzcpR5QIHYVTMukXX4u4qTZ8X5QMGz8oF7L9W68W3Fi8pN_gXgMZg-yO4MLK5Wp4nuJfZi0jW_R5thXo" alt="A screenshot showing the Create function button" width="1600" height="917"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up the email contact form&lt;/strong&gt;&lt;br&gt;
This phase involves selecting a runtime environment, adding the credentials obtained from Mailgun, and setting up the GitHub repository. &lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Node.js - 16.0&lt;/strong&gt; as the runtime environment, then click &lt;strong&gt;Next.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FCCJ6cauua5DG0B65Od3eTm9OI9pqbgWxOfkMxdG4H4ehM2VJvd1Ma7fjMVZIfffK_MZQeNTjuTJmgoLE0Z2068Zl7EeD8k3sy1ieES-SDy7Uf4gntC9xrfKUGZbf9gRSma7TBMaV0zqa9W9GiFmreo0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FCCJ6cauua5DG0B65Od3eTm9OI9pqbgWxOfkMxdG4H4ehM2VJvd1Ma7fjMVZIfffK_MZQeNTjuTJmgoLE0Z2068Zl7EeD8k3sy1ieES-SDy7Uf4gntC9xrfKUGZbf9gRSma7TBMaV0zqa9W9GiFmreo0" alt="A screenshot showing the section to select the runtime environment for your email contact form" width="1600" height="919"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, add the credentials obtained from Mailgun, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FXf5bdi-GsXZqRbLmp9zdM4lMXrC9r44wuUatPn_jASFX24mD6aZM1Y7opnuzGgOO93KumduVHszQ4jYUj_6e5s5ywtRvRkGJA-apH2pYpur_oCGc2ENM0l1VcYQ22Zp4TAvnX5dQBagjr-jugaqdRJI" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FXf5bdi-GsXZqRbLmp9zdM4lMXrC9r44wuUatPn_jASFX24mD6aZM1Y7opnuzGgOO93KumduVHszQ4jYUj_6e5s5ywtRvRkGJA-apH2pYpur_oCGc2ENM0l1VcYQ22Zp4TAvnX5dQBagjr-jugaqdRJI" alt="A screenshot showing the section to enter the credentials from Mailgun" width="1600" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The template sends the email leads to the email address provided in the &lt;strong&gt;SUBMIT_EMAIL&lt;/strong&gt; field. Add your preferred email to the field, and then click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When using Mailgun's sandbox environment, make sure the email address you provided in the &lt;strong&gt;SUBMIT_EMAIL&lt;/strong&gt; field is authorized within Mailgun's system. For additional information, please visit this &lt;a href="https://help.mailgun.com/hc/en-us/articles/217531258-Authorized-Recipients?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;link&lt;/a&gt;. Also, note that emails sent using the sandbox environment are usually sent to the spam folder of the receiving email account.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Connecting and setting up your GitHub repository&lt;/strong&gt;&lt;br&gt;
At this point, you need to connect your GitHub repository to the platform. Appwrite pushes a copy of the template to your GitHub account, allowing you to personalize your version as required.&lt;/p&gt;

&lt;p&gt;Click on the GitHub option as indicated below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FIMkGAD9cc5Dd7PnV7bB4UzQojP9lSHFYFhWloZRo5gDHCY1uf9wpJYcy6zokHESW8VcCNkcsVv9JTlx6umQY-vW9Fl-LkLHiVfYp3eN9tM0uHYG1CoKbP2objdZU8Oi5NroEI_-8qXkK0WYZx7B0OP8" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FIMkGAD9cc5Dd7PnV7bB4UzQojP9lSHFYFhWloZRo5gDHCY1uf9wpJYcy6zokHESW8VcCNkcsVv9JTlx6umQY-vW9Fl-LkLHiVfYp3eN9tM0uHYG1CoKbP2objdZU8Oi5NroEI_-8qXkK0WYZx7B0OP8" width="1600" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your GitHub account is not yet connected to Appwrite, you will be redirected to GitHub to complete the connection process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2Fc_yGxEnkCnfCxYpUIvCion1D9rBDdNLS_pX13pA9eGwr4-WLipnryyjo67-V1iR3dAnnBtja3-AQYEasMqxQIIJ85NHTzlsEFulyzxL7NAmzWFWZbXZnohjZJMQK8xm_Rcbep3QOLtYu6rC0zOFlEtU" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2Fc_yGxEnkCnfCxYpUIvCion1D9rBDdNLS_pX13pA9eGwr4-WLipnryyjo67-V1iR3dAnnBtja3-AQYEasMqxQIIJ85NHTzlsEFulyzxL7NAmzWFWZbXZnohjZJMQK8xm_Rcbep3QOLtYu6rC0zOFlEtU" width="1600" height="1032"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Afterward, choose the repository that was created as part of the prerequisite.&lt;/p&gt;

&lt;p&gt;If you already have a GitHub account connected to your Appwrite cloud account, select the &lt;strong&gt;Add to existing repository&lt;/strong&gt; option instead of &lt;strong&gt;Create a new repository&lt;/strong&gt; and click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2F2K4r2EMrI3wz5WacjUoHhw15ZhTh90StyCJYFbV7ALjXIr0bFJueQhmyQHXNGrgI5XemHG6Ofr9B9u0-Eeuua1PpMZPlcpRNtMSrFW9o83JE4o0E0sKUp1jB1vX9u8Z6e4c2Dcup3jjZ5bePu_H5kpk" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2F2K4r2EMrI3wz5WacjUoHhw15ZhTh90StyCJYFbV7ALjXIr0bFJueQhmyQHXNGrgI5XemHG6Ofr9B9u0-Eeuua1PpMZPlcpRNtMSrFW9o83JE4o0E0sKUp1jB1vX9u8Z6e4c2Dcup3jjZ5bePu_H5kpk" alt="A screenshot showing the add to existing repository option" width="1600" height="916"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select the GitHub account and the repository of your choice, then click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2F0xOeXeEbxRMIlDyVIedwAhH5L2wqoKDSK138GXxiV_DViAVpxcDYDchHDY7zeR1T9HHAsuKRvEhSdZLCT-ezLNSV9XHDjycxIeT313kHk2946XO4oF4MNvdibzGHZ47XUOFcTwe-4On1qxj2GkXxQ8o" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2F0xOeXeEbxRMIlDyVIedwAhH5L2wqoKDSK138GXxiV_DViAVpxcDYDchHDY7zeR1T9HHAsuKRvEhSdZLCT-ezLNSV9XHDjycxIeT313kHk2946XO4oF4MNvdibzGHZ47XUOFcTwe-4On1qxj2GkXxQ8o" width="1600" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, select the branch you want to use and add the root directory as &lt;strong&gt;function/src,&lt;/strong&gt; then click &lt;strong&gt;Create&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FHOoNC_gi1tLQ3bgcZTCpuwXMCpknndtTd3xgUXIxvkY_KsbgoKsZf7Ggiz-HlttW2_m3KTyfmCS0RwPbbqtGGnFgul1PLuB72mVAfRPITSANHQwmJrdpWvQTfO1ysJcoHTvfTr_ZBNg8yVqVyfs-MNU" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FHOoNC_gi1tLQ3bgcZTCpuwXMCpknndtTd3xgUXIxvkY_KsbgoKsZf7Ggiz-HlttW2_m3KTyfmCS0RwPbbqtGGnFgul1PLuB72mVAfRPITSANHQwmJrdpWvQTfO1ysJcoHTvfTr_ZBNg8yVqVyfs-MNU" width="1600" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your email contact form template is set to deploy automatically once a copy of the template's code is successfully pushed to your repository. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FV8N_TbbuekeAH3Bk5CWEadUQBg3L9TY8jlpLMkUhi3ni3l33zfyQRs0qXhJDniFLQrjJDR0Yhcr_g4J1r0iqImhUzV57nKkFC21fTsfrTqH1nbkz403Ry0zHAI9mvvAWacqTAtGEOtPCJZPXGlSzOEg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FV8N_TbbuekeAH3Bk5CWEadUQBg3L9TY8jlpLMkUhi3ni3l33zfyQRs0qXhJDniFLQrjJDR0Yhcr_g4J1r0iqImhUzV57nKkFC21fTsfrTqH1nbkz403Ry0zHAI9mvvAWacqTAtGEOtPCJZPXGlSzOEg" alt="A screenshot showing the content of the function on your GitHub repository" width="1600" height="918"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, navigate to your Appwrite cloud dashboard to confirm the function was deployed successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FFrgVT0KuF3cgNQuXEUv7TC-MqWiKvzFTdyIlhLA_1rwGyEbIK_3NzmLwcNuOYlnnUPWmmuAfcu_fBhqeqCE-S5Q8TGtWGLFxOY1RatDHXf9wX38gLeg6g-TqeOpUknTIpiww_39JnIaXFR7tKqUHrPI" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh7-us.googleusercontent.com%2FFrgVT0KuF3cgNQuXEUv7TC-MqWiKvzFTdyIlhLA_1rwGyEbIK_3NzmLwcNuOYlnnUPWmmuAfcu_fBhqeqCE-S5Q8TGtWGLFxOY1RatDHXf9wX38gLeg6g-TqeOpUknTIpiww_39JnIaXFR7tKqUHrPI" alt="A screenshot showing the successfully deployed function" width="1600" height="919"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up your leads collection Next.js website
&lt;/h2&gt;

&lt;p&gt;For this step, you'll create your Next.js leads collection page and integrate Appwrite into the project.&lt;/p&gt;

&lt;p&gt;To get started, navigate to your terminal and run the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app@latest leads_pages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This command prompts you to select other packages to be used by the project. Select the options as indicated in the screenshot below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7ahp9mdmbbqm5pvwdyh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7ahp9mdmbbqm5pvwdyh.png" alt="A screenshot showing the selected options after running the create-project command" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once completed, run the command below to change the current working directory to the project's directory.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd leads_pages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Next, install your project's Appwrite SDK dependency by running this command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add appwrite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Afterward, open the project on your code editor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding your environment variables.&lt;/strong&gt;&lt;br&gt;
In the root directory of your project, create a file &lt;strong&gt;.env,&lt;/strong&gt; then add the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEXT_PUBLIC_APPWRITE_FUNCTION_ID=&amp;lt;function_id&amp;gt;
NEXT_PUBLIC_APPWRITE_BASE_URL=https://cloud.appwrite.io/v1
NEXT_PUBLIC_APPWRITE_PROJECT_ID=&amp;lt;project_id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;You can retrieve your &lt;code&gt;&amp;lt;function_id&amp;gt;&lt;/code&gt;  and &lt;code&gt;&amp;lt;project_id&amp;gt;&lt;/code&gt; Appwrite credentials from the Appwrite dashboard. Replace the &lt;code&gt;&amp;lt;function_id&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;project_id&amp;gt;&lt;/code&gt; with the corresponding credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating your leads collection custom hook&lt;/strong&gt;&lt;br&gt;
To promote reusability and modularity, you'll need to create the logic that handles collecting and sending the user's input to Appwrite. &lt;/p&gt;

&lt;p&gt;To proceed, create a new folder, &lt;strong&gt;hooks&lt;/strong&gt; in the &lt;strong&gt;src/&lt;/strong&gt; directory. &lt;br&gt;
Next, create a file &lt;strong&gt;useLeadCollector.tsx,&lt;/strong&gt; then add the following:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the snippet above, there are two states, which include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;request&lt;/code&gt; state: This keeps track of the state of the asynchronous action when the collectLeads function is called.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;form&lt;/code&gt; state: This stores the value coming from the user input.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;collectLeads&lt;/strong&gt; function handles requests to the Appwrite Function specified by the &lt;code&gt;process.env.NEXT_PUBLIC_APPWRITE_FUNCTION_ID&lt;/code&gt; and &lt;code&gt;process.env.NEXT_PUBLIC_APPWRITE_FUNCTION_KEY&lt;/code&gt;. The email contact form function requires the request body to be sent using the &lt;strong&gt;content-type&lt;/strong&gt; &lt;code&gt;application/x-www-form-urlencoded.&lt;/code&gt; Additionally, be sure to set the &lt;strong&gt;referrer&lt;/strong&gt; header for proper functionality. &lt;/p&gt;

&lt;p&gt;Once the &lt;strong&gt;collectLeads&lt;/strong&gt; function is called, the request state is toggled to &lt;strong&gt;loading&lt;/strong&gt;, which changes the user interface to the loading interface. Next, the &lt;strong&gt;throwErrorIfNot200&lt;/strong&gt; function handles errors returned from the Appwrite Function. If the request is successful, then the request state will be set to &lt;strong&gt;completed&lt;/strong&gt;; otherwise, it will be set to &lt;strong&gt;error&lt;/strong&gt;. After a 5-second delay on &lt;strong&gt;error&lt;/strong&gt;, the state will be toggled to &lt;strong&gt;idle&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating your page components&lt;/strong&gt;&lt;br&gt;
To build the leads page, you'll be creating various components. Here's a breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Header:&lt;/strong&gt; This component houses the introductory content for the leads page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;About:&lt;/strong&gt; Offers additional information to capture the lead's interest.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JoinSteps:&lt;/strong&gt; Elaborates on the information discussed in the previous sections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Footer:&lt;/strong&gt; Provides hyperlinks to different application sections and includes copywriter information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Form:&lt;/strong&gt; An abstracted form interface for user interaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contact:&lt;/strong&gt; The crucial section for collecting leads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To organize your project, navigate to the &lt;strong&gt;src/&lt;/strong&gt; directory and create a folder named &lt;strong&gt;components&lt;/strong&gt; to store these page components.&lt;/p&gt;

&lt;p&gt;Starting with the &lt;strong&gt;Header&lt;/strong&gt; component, create a file &lt;strong&gt;Header.tsx&lt;/strong&gt; in the &lt;strong&gt;components&lt;/strong&gt; folder, then add the following code snippet.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Next, create the About component by repeating the steps above, create the &lt;strong&gt;About.tsx&lt;/strong&gt; file, and add the following:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;After that, create the &lt;strong&gt;Footer&lt;/strong&gt; component by creating the &lt;strong&gt;Footer.tsx&lt;/strong&gt; file and adding the following:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Moving on to the &lt;strong&gt;JoinSteps&lt;/strong&gt; component, create the &lt;strong&gt;JoinSteps.tsx&lt;/strong&gt; file and add the code snippet below.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Next, let's create the Form component. Start by creating a folder named &lt;strong&gt;partials&lt;/strong&gt; within the &lt;strong&gt;components&lt;/strong&gt; directory. Inside this &lt;strong&gt;partials&lt;/strong&gt; folder, create a file &lt;strong&gt;Form.tsx&lt;/strong&gt;. Copy and paste the following snippet into the &lt;strong&gt;Form.tsx&lt;/strong&gt; file:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Last but not least is the &lt;strong&gt;Contact&lt;/strong&gt; component. Create the &lt;strong&gt;Contact.tsx&lt;/strong&gt; file and add the following:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;In the provided snippet, the Form component is rendered based on the value of the &lt;code&gt;request&lt;/code&gt; state. If the request state is &lt;strong&gt;idle&lt;/strong&gt;, then the Form component is rendered. Similarly, other request states are handled likewise.&lt;/p&gt;

&lt;p&gt;The use of "use client" signifies that the Contact component is client-side. This is necessary because, by default, Next.js sets all components to server-side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding the components to the leads page&lt;/strong&gt;&lt;br&gt;
Once the components are created successfully, you’ll need to add them to the leads landing page. &lt;br&gt;
To do so, open the &lt;strong&gt;page.tsx&lt;/strong&gt; file in the &lt;strong&gt;src/app&lt;/strong&gt; directory and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;About&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/About&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Contact&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/Contact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Footer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/Footer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/Header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;JoinSteps&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/components/JoinSteps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;min-h-screen text-center px-24 py-10&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;max-w-[1000px] mx-auto pb-24 bg-white&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;About&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;JoinSteps&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Contact&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Footer&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The above snippet renders the components for the user to interact with.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing your leads page&lt;/strong&gt;&lt;br&gt;
To display the page on the browser, navigate to your project's terminal and run the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This command sets up a local server environment from the project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejmn4tymfb39y2bcj8i6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fejmn4tymfb39y2bcj8i6.png" alt="A screenshot showing the running environment for the project" width="800" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Extract the URL (&lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;) from your terminal and visit the page on your browser. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggt8ds38eui4yd17uv7h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggt8ds38eui4yd17uv7h.png" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a demonstration of the working system.&lt;/p&gt;


&lt;div&gt;
  &lt;iframe src="https://loom.com/embed/77f6c30646764888b3f5b7e7b5f0a675"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By combining the capabilities of Appwrite and Mailgun, you can quickly set up your email marketing leads collector, streamline lead collection, and ultimately launch more successful marketing campaigns. The user-friendly setup and detailed instructions make this tutorial accessible even for those with minimal JavaScript and Git knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/hackmamba/how-to-automate-appwrite-functions-deployment-with-github-95e"&gt;How to automate Appwrite Functions deployment with GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs/products/functions?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Appwrite Function documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://documentation.mailgun.com/en/latest/?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Mailgun documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.github.com/en" rel="noopener noreferrer"&gt;Git&lt;/a&gt;&lt;a href="https://docs.github.com/en" rel="noopener noreferrer"&gt;H&lt;/a&gt;&lt;a href="https://docs.github.com/en" rel="noopener noreferrer"&gt;ub documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/" rel="noopener noreferrer"&gt;Next.js documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How to automate Appwrite Functions deployment with GitHub</title>
      <dc:creator>Obisike Treasure</dc:creator>
      <pubDate>Mon, 30 Oct 2023 16:21:55 +0000</pubDate>
      <link>https://dev.to/hackmamba/how-to-automate-appwrite-functions-deployment-with-github-95e</link>
      <guid>https://dev.to/hackmamba/how-to-automate-appwrite-functions-deployment-with-github-95e</guid>
      <description>&lt;p&gt;Cloud functions are powerful tools for developing applications and reducing server costs. &lt;a href="https://appwrite.io/docs/products/functions?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Appwrite Functions&lt;/a&gt;, a cloud function service offered by the backend-as-a-service platform &lt;a href="https://appwrite.io/?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Appwrite&lt;/a&gt;, offers the flexibility and efficiency for implementing serverless solutions effortlessly.&lt;/p&gt;

&lt;p&gt;Appwrite functions must be deployed, but manual deployment can lead to insufficient version control, wasted time, inconsistent app environments, and exposure of secret environment variables, all of which can cause errors and security issues. Automating your deployments with &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; can help avoid these problems.&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll learn the benefits of automating Appwrite function deployments and explore the step-by-step process of automating your Appwrite function deployments using GitHub without manually configuring environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you dive into the automation process, you'll need to ensure you have the following prerequisites covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Basic knowledge of Node.js&lt;/strong&gt;: You should have a foundational understanding of &lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;, which is commonly used for developing serverless functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An Appwrite cloud account&lt;/strong&gt;: To use Appwrite functions, you need to have an active Appwrite cloud account. If you don't have one, sign up on the &lt;a href="https://cloud.appwrite.io/register?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Appwrite&lt;/a&gt; &lt;a href="https://appwrite.io/" rel="noopener noreferrer"&gt;website&lt;/a&gt; to get started.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A basic knowledge of Git and a GitHub account:&lt;/strong&gt; You'll need a GitHub account to set up your repository. If you don't have one, sign up at &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full project is in this &lt;a href="https://github.com/trex013/seo-analyser.git" rel="noopener noreferrer"&gt;repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Appwrite and GitHub repository
&lt;/h2&gt;

&lt;p&gt;Get started by creating a GitHub repository using these &lt;a href="https://docs.github.com/en/get-started/quickstart/create-a-repo" rel="noopener noreferrer"&gt;instructions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, you’ll need to create a project within the Appwrite Cloud console. If you just signed up, you’ll be immediately prompted to create a project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fptf3omj20o0xjt1k4ilr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fptf3omj20o0xjt1k4ilr.png" alt="A screenshot the project’s name field" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If not, click on the &lt;strong&gt;Create a new Project,&lt;/strong&gt; as indicated below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fds12tum6i2wrgooiiarz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fds12tum6i2wrgooiiarz.png" alt="A screenshot showing the Create a new project" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you've finished this step, you'll be able to see the dashboard for your project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Formc9ak15pmf042euzfq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Formc9ak15pmf042euzfq.png" alt="A screenshot showing the project’s dashboard" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating your Appwrite Function on Appwrite
&lt;/h2&gt;

&lt;p&gt;Next, you’ll need to create your function on the Appwrite console. To continue, click the &lt;strong&gt;F&lt;/strong&gt;&lt;strong&gt;unctions&lt;/strong&gt; menu on the navigation bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrv1ck20i5tzslmxuvzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxrv1ck20i5tzslmxuvzz.png" alt="A screenshot showing the Functions menu" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Afterward, click the &lt;strong&gt;Create function&lt;/strong&gt; button indicated below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu45uxqg6jzaj4bld29t1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu45uxqg6jzaj4bld29t1.png" alt="A screenshot showing the Create function button" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, select the starter template you’d like to use. For this case, click &lt;strong&gt;Node.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxs9pie4bs6xjgcvbsvl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frxs9pie4bs6xjgcvbsvl.png" alt="A screenshot showing Node.js selection" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the name of your function and select &lt;strong&gt;Node.js - 18.0&lt;/strong&gt; as the runtime. Then, click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67s4riqmb3nsnufn6zqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67s4riqmb3nsnufn6zqi.png" alt="A screenshot showing the create function configuration screen" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the next step, Appwrite gives you the option to use an existing API key or generate a new one. To continue with this tutorial, select the &lt;strong&gt;Generate API key on completion&lt;/strong&gt; checkbox, then click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4bc1oob61it8waje80c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4bc1oob61it8waje80c.png" alt="A screenshot showing the section to select the generate API key section" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you can choose to use an existing repository or have Appwrite clone the template to a new one. Select &lt;strong&gt;Create a new repository&lt;/strong&gt;, then click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxig99bt851lufng3bu6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsxig99bt851lufng3bu6.png" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you've completed that step, you’ll need to connect your GitHub account to your Appwrite console. Click on the GitHub option as indicated below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9e4bmsr5kflq814nfgur.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9e4bmsr5kflq814nfgur.png" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you haven’t connected your GitHub account to Appwrite, you’ll be redirected to GitHub to do so.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58gag7jun14ytd7pw4zk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58gag7jun14ytd7pw4zk.png" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Make sure to select the repository you initially created.&lt;/p&gt;

&lt;p&gt;Once that’s done, enter the name of the new repository and click &lt;strong&gt;Next&lt;/strong&gt;. This step specifies the name of the new repository Appwrite will create on your GitHub account. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo77n3gtomxz4ivijob3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvo77n3gtomxz4ivijob3.png" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, select your desired Git branch and enter the root directory of your function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qhpp7nt0q8ycai750m5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8qhpp7nt0q8ycai750m5.png" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, the function has been successfully created and deployed on your Appwrite cloud account. Subsequent deployments will be triggered when you push changes to the GitHub repository Appwrite created for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0p7ume6mmm8fibocxbuo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0p7ume6mmm8fibocxbuo.png" alt="A screenshot showing the deployments" width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding your Appwrite Function code
&lt;/h2&gt;

&lt;p&gt;Now that you've created the Appwrite Function, it's time to update the template in the GitHub repository generated by Appwrite on your GitHub account.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The GitHub repository created by Appwrite is usually a private repository. Therefore, it’s preferred that you use SSH to clone this repository. Check &lt;a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh" rel="noopener noreferrer"&gt;here&lt;/a&gt; to configure SSH on your GitHub account.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To continue, go to your GitHub repository created by Appwrite, and then follow these &lt;a href="https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository" rel="noopener noreferrer"&gt;steps&lt;/a&gt; to clone your repository locally. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foucpfxk89sr5m467s9vz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foucpfxk89sr5m467s9vz.png" width="800" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the repository is successfully cloned, open the projects folder with your code editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe8o0p7e8vwpew5pzty66.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe8o0p7e8vwpew5pzty66.png" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;main.js&lt;/strong&gt; file is the entry point for the function, which means that this is where you should place your function code.&lt;/p&gt;

&lt;p&gt;Open the &lt;strong&gt;main.js&lt;/strong&gt; file and replace its contents with the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;cheerio&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cheerio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getSEOInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cheerio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`h&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`h&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metaDescription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;meta[name=description]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metaKeywords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;meta[name=keywords]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;canonicalURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;link[rel=canonical]&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;internalLinks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a[href^="/"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;externalLinks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a[href^="http"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;metaDescription&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;metaKeywords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;canonicalURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;internalLinks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;externalLinks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Request method not supported&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getSEOInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;failed to get SEO information&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above uses &lt;a href="https://axios-http.com/" rel="noopener noreferrer"&gt;axios&lt;/a&gt; to fetch the content of a given URL and &lt;a href="https://cheerio.js.org/?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;cheerio&lt;/a&gt; to extract the SEO information.&lt;/p&gt;

&lt;p&gt;After that, run the following command to install the project’s package dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add axios cheerio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Triggering and testing the deployment
&lt;/h2&gt;

&lt;p&gt;Once you're finished developing your function locally, you can deploy it by committing your changes to Git and pushing them to the GitHub repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi66zudtxden8bv8kqd16.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi66zudtxden8bv8kqd16.png" alt="A screenshot showing the recent deployment" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You’ll notice that a new deployment has been added to the list of deployments.&lt;/p&gt;

&lt;p&gt;To test your deployment, click &lt;strong&gt;Execute now&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foaaxezk7d8g1owwvzaaq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foaaxezk7d8g1owwvzaaq.png" width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, add the parameters required by your function. In this case, you’re adding a query parameter &lt;code&gt;url&lt;/code&gt; as indicated below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnaknlrdj8qysfrjswuzl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnaknlrdj8qysfrjswuzl.png" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Afterwards, click &lt;strong&gt;Execute&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9jl0wfix93eyebbk693.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv9jl0wfix93eyebbk693.png" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the execution to view more information about it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwe0v0dt116h5y20pxxv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwe0v0dt116h5y20pxxv.png" alt="A screenshot showing the function execution" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Automating your Appwrite function deployments using this method is a great way to streamline your development and deployment workflows, free up valuable time, and improve efficiency while eliminating the need to add your Appwrite environment variables to GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs/products/functions?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Appwrite Function documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.github.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt;&lt;a href="https://docs.github.com/" rel="noopener noreferrer"&gt;H&lt;/a&gt;&lt;a href="https://docs.github.com/" rel="noopener noreferrer"&gt;ub documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://axios-http.com/" rel="noopener noreferrer"&gt;Axios documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cheerio.js.org/?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Cheerio documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to add DigitalOceans Spaces adapter to an Appwrite instance</title>
      <dc:creator>Obisike Treasure</dc:creator>
      <pubDate>Thu, 21 Sep 2023 14:59:37 +0000</pubDate>
      <link>https://dev.to/hackmamba/how-to-add-digitaloceans-spaces-adapter-to-an-appwrite-instance-2jde</link>
      <guid>https://dev.to/hackmamba/how-to-add-digitaloceans-spaces-adapter-to-an-appwrite-instance-2jde</guid>
      <description>&lt;p&gt;The rapid development of the Internet has created an unprecedented need for better storage. The current state of web development makes it crucial for applications to utilize services such as user authentication, file storage, and data delivery. Fortunately, &lt;a href="https://appwrite.io/?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Appwrite&lt;/a&gt; offers a solution that includes these services, eliminating the need for complex server setup and management.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Appwrite?
&lt;/h2&gt;

&lt;p&gt;Appwrite is an all-in-one solution offering backend services such as authentication, databases, and file storage. It's user-friendly and can be self-hosted or used as a cloud service. &lt;br&gt;
To overcome storage limitations encountered when using a self-hosted Appwrite instance, Appwrite allows you to extend its storage service using several external storage services, such as &lt;a href="https://www.digitalocean.com/products/spaces?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://www.digitalocean.com/products/spaces?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;DigitalOcean Spaces&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is DigitalOcean Spaces?
&lt;/h2&gt;

&lt;p&gt;DigitalOcean Spaces is an object storage service offered by DigitalOcean, a popular cloud infrastructure provider. Spaces allows you to store and serve large amounts of data, such as images, videos, and other files, in a scalable and cost-effective manner.&lt;br&gt;
This resilient, secure, and cost-effective file storage solution can seamlessly connect with Appwrite via an adapter, enhancing the storage service offered by the Appwrite instance.&lt;/p&gt;
&lt;h2&gt;
  
  
  Benefits of extending Appwrite storage service with DigitalOcean Spaces
&lt;/h2&gt;

&lt;p&gt;Adding the DigitalOcean's Spaces adapter to an Appwrite instance essentially extends Appwrite's storage service. This extension offers the following advantages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability and performance&lt;/strong&gt;: As your application gains traction, the need for storage increases. DigitalOcean’s Spaces scales seamlessly, accommodating large data volumes. Merging it with Appwrite ensures smooth performance and efficient data handling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt; &lt;strong&gt;efficiency&lt;/strong&gt;: Unlike conventional server-based storage, Spaces lets you pay solely for used storage, a budget-friendly choice to expand your Appwrite app minus unnecessary costs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backup&lt;/strong&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;strong&gt;recovery&lt;/strong&gt; &lt;strong&gt;made&lt;/strong&gt; &lt;strong&gt;simple&lt;/strong&gt;: With Spaces, crafting Appwrite backups is straightforward. Regular backups ensure that you're well-prepared for unforeseen data loss incidents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Next, let's dive into extending your self-hosted Appwrite service with DigitalOcean’s Spaces by building a &lt;strong&gt;media-gallery application&lt;/strong&gt; and adding the storage service.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Tutorial: Building a Nuxt.js media-gallery application
&lt;/h2&gt;

&lt;p&gt;Here we’ll build a media gallery application using Nuxt.js, self-hosting Appwrite, extending Appwrite storage with DigitalOcean Spaces, and linking the storage to the application. The project repository can be found &lt;a href="https://github.com/Otrex/nuxt-media-gallary" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The application's functionalities will include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating image galleries.&lt;/li&gt;
&lt;li&gt;Storing and displaying created galleries.&lt;/li&gt;
&lt;li&gt;Generating shareable links for the galleries.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;The following requirements apply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of JavaScript, &lt;a href="https://vuejs.org/" rel="noopener noreferrer"&gt;Vue.js&lt;/a&gt;, and &lt;a href="https://nuxt.com/" rel="noopener noreferrer"&gt;Nuxt.js&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; and &lt;a href="https://classic.yarnpkg.com/en/" rel="noopener noreferrer"&gt;Yarn&lt;/a&gt; installed on your computer.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; installed for local hosting of Appwrite.&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://www.digitalocean.com/?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt; account to create and access Spaces.
## Setting up DigitalOcean Spaces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To set up your DigitalOcean Spaces, create a new Spaces bucket on DigitalOcean and extract the Spaces Bucket access credentials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating a new Spaces Bucket&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To get started, log into your DigitalOcean account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FBiQ5WrbtXyx4VsdEOG9G9H6UXY082-arK0_BW-FJTCWZHfrpmV1ifRruytmmgzffLWnVdb7sykbjbfZBaeSdu48n9o6wlDZF5pM1zXzxOQLecL5yCsup2BgBANra-ymKIhDkRv5qtW9FKchlenHYV8k" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FBiQ5WrbtXyx4VsdEOG9G9H6UXY082-arK0_BW-FJTCWZHfrpmV1ifRruytmmgzffLWnVdb7sykbjbfZBaeSdu48n9o6wlDZF5pM1zXzxOQLecL5yCsup2BgBANra-ymKIhDkRv5qtW9FKchlenHYV8k" alt="A screenshot showing the DigitalOcean platform" width="760" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Store static objects&lt;/strong&gt;, which takes you to the section for creating Spaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2FD2YQB0GqfIC4ub25VsY0Es0w9dS4-6F6L1QIjGNqtBmRfhkASQsjtpqWiHU2LH8u_RyOavGwKl_EK4VSAGSvD-Is9h1AyquTA3JGAKZ8CDYsMRRG0vIemt35xwnMtHWmTmE95zofX-589AI3x058j1Y" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2FD2YQB0GqfIC4ub25VsY0Es0w9dS4-6F6L1QIjGNqtBmRfhkASQsjtpqWiHU2LH8u_RyOavGwKl_EK4VSAGSvD-Is9h1AyquTA3JGAKZ8CDYsMRRG0vIemt35xwnMtHWmTmE95zofX-589AI3x058j1Y" alt="A screenshot showing the Spaces creation interface" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Afterward, keep the default values for &lt;strong&gt;Choose a datacenter region&lt;/strong&gt; and the content delivery network (CDN). Enter your preferred bucket name in the &lt;strong&gt;Choose a unique Spaces Bucket name&lt;/strong&gt; section. For this tutorial, you’ll be using &lt;strong&gt;nuxt-gallery&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Usually, a Spaces Bucket is linked to a project. For this guide, you’ll use the default project created by Digital Ocean when you sign up successfully.&lt;/p&gt;

&lt;p&gt;Next, click &lt;strong&gt;Create a Spaces Bucket&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FW4g_N2oSPgV4-KwJeff2VEtQ4waj8_FMIwZb1TRNei4bLQssu8aTPsUSw4btawxLKF5QWvbvXlW4zqOca7g7Ev_boUM2w3Uty1Wvjc1m7YAMcmz3ueHYtZP7b1bWJ54VmQ6sBmcTF99CIqXkxqcZjcE" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FW4g_N2oSPgV4-KwJeff2VEtQ4waj8_FMIwZb1TRNei4bLQssu8aTPsUSw4btawxLKF5QWvbvXlW4zqOca7g7Ev_boUM2w3Uty1Wvjc1m7YAMcmz3ueHYtZP7b1bWJ54VmQ6sBmcTF99CIqXkxqcZjcE" alt="A screenshot showing the Create a Spaces Bucket" width="1600" height="919"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your Spaces bucket will be created and assigned an &lt;strong&gt;Origin Endpoint.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FQJt0fln0SMgAJlMrkNRuu7JVxzNANbMOoFe7Km4-qX850mQGm7zzn_Eq2DIctFySI6xrugymLgRdiZUlb1idBw2GQ0dn802Vs1LUKv26nIBUWG7CiUb8HSRH0pnCwNGvEFzwZB0p7w8q-G9_q17xbNQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FQJt0fln0SMgAJlMrkNRuu7JVxzNANbMOoFe7Km4-qX850mQGm7zzn_Eq2DIctFySI6xrugymLgRdiZUlb1idBw2GQ0dn802Vs1LUKv26nIBUWG7CiUb8HSRH0pnCwNGvEFzwZB0p7w8q-G9_q17xbNQ" alt="A screenshot showing the created bucket" width="760" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you’ll need to enable anyone to access the content on your bucket. To do this, click on the &lt;strong&gt;Settings&lt;/strong&gt; tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2F9J4HuCoiLXLmZ_PLz81QN7IqeT7gg19fidphou99XjvuTk6Ao2F3tUgdUe3F9Zz_JlEhZdoELJogcQAeL5YRJi6yqiPYnVzA3WUNJWSMyqaWpqzpERuLRNqE5t0AqrjbhpZRLJ0S39xjNLs7YyLpO8E" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2F9J4HuCoiLXLmZ_PLz81QN7IqeT7gg19fidphou99XjvuTk6Ao2F3tUgdUe3F9Zz_JlEhZdoELJogcQAeL5YRJi6yqiPYnVzA3WUNJWSMyqaWpqzpERuLRNqE5t0AqrjbhpZRLJ0S39xjNLs7YyLpO8E" alt="A screenshot showing the nuxt-gallery settings tab" width="760" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then on the &lt;strong&gt;File Listing&lt;/strong&gt; section, click &lt;strong&gt;Edit.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FBRTMgEZ7i4AHANtDAwKweO14YqRaFn4zNMlDqIFUg924gZxWLFdwh8wKJs9w8cLBlf75SK0Q4lqHtKVUpHAeiHS1q-__95PfSdsxV-IrhiShHL5ag5n7j-AtlAQEVOosn_U-ej6AlkHACeeqGxdo_Uo" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FBRTMgEZ7i4AHANtDAwKweO14YqRaFn4zNMlDqIFUg924gZxWLFdwh8wKJs9w8cLBlf75SK0Q4lqHtKVUpHAeiHS1q-__95PfSdsxV-IrhiShHL5ag5n7j-AtlAQEVOosn_U-ej6AlkHACeeqGxdo_Uo" alt="A screenshot showing the file listing section" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, select &lt;strong&gt;Enable File Listing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FtsXxkdSOBsb65r0J54hNWdK_1TnHAtIUYxY1wUgW1au7xtW_nLeOBmTwfBU3Jb5AOzRgV54IIgfsDYd4q28MS7Mkpzhu3NzwHQIuI2R3b82G78VSDlGzB4qSLe9O0HENz4SvH2IE_BSvRZdkO_0K-Gg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FtsXxkdSOBsb65r0J54hNWdK_1TnHAtIUYxY1wUgW1au7xtW_nLeOBmTwfBU3Jb5AOzRgV54IIgfsDYd4q28MS7Mkpzhu3NzwHQIuI2R3b82G78VSDlGzB4qSLe9O0HENz4SvH2IE_BSvRZdkO_0K-Gg" alt="A screenshot showing the Enable File Listing option" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting the Spaces Access Keys&lt;/strong&gt;&lt;br&gt;
Next, you’ll need to retrieve the following keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;bucket-name&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;access-key&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;access-secret&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;bucket-region&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bucket URL can be found in the &lt;strong&gt;Origin Endpoint&lt;/strong&gt; indicated below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2F6GwHTVgL_8G8fVbKVQeIvcDJ-Ok9zqAcKCXxTSFGODowgDVJ3GhFlk_kofCIYWjUatAuNr_hyEw05rhvYfMVsQkKOZ2ez-QR0h3N1Fc1KhyRLmv0sQD8Du3D0qTboeaD_eODqVSA6aHuTbqTvjkWEr0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2F6GwHTVgL_8G8fVbKVQeIvcDJ-Ok9zqAcKCXxTSFGODowgDVJ3GhFlk_kofCIYWjUatAuNr_hyEw05rhvYfMVsQkKOZ2ez-QR0h3N1Fc1KhyRLmv0sQD8Du3D0qTboeaD_eODqVSA6aHuTbqTvjkWEr0" alt="A screenshot showing the bucket URL" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This bucket URL contains the &lt;code&gt;&amp;lt;bucket-name&amp;gt;&lt;/code&gt; and the &lt;code&gt;&amp;lt;bucket-region&amp;gt;&lt;/code&gt; in the form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://&amp;lt;bucket-name&amp;gt;.&amp;lt;bucket-region&amp;gt;.digitaloceanspaces.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then extract these keys from the URL on your dashboard.&lt;/p&gt;

&lt;p&gt;Next, the &lt;code&gt;&amp;lt;access-key&amp;gt;&lt;/code&gt; can be obtained by navigating to &lt;strong&gt;API menu.&lt;/strong&gt; Click on &lt;strong&gt;API.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FBHwkMYwGBjU2P01CjLVfLNG7csfmLjI5d9jB4jDkznuCvObAMFNU4JsRA-5L6bp265cPXhg0AukGTw7nCdx6edEApESpLxGM8H4pPZlK99c0XlRytO4n8JSW-sk5zB6ENGIiyhN8QFee1EgeuWk7Y80" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FBHwkMYwGBjU2P01CjLVfLNG7csfmLjI5d9jB4jDkznuCvObAMFNU4JsRA-5L6bp265cPXhg0AukGTw7nCdx6edEApESpLxGM8H4pPZlK99c0XlRytO4n8JSW-sk5zB6ENGIiyhN8QFee1EgeuWk7Y80" alt="A screenshot showing the API menu on the navigation bar" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, click on &lt;strong&gt;Spaces Key.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FkXLVpTEowt-lS_-_Aog7QYBdydeA7I5PNrK-01QiGCIPJJOQeMRR9LvwGpeNzXzmR4wUrBda9OjDZbbVKcEDRiTYJzmpo6sj8bMu9DuIIsF_1cp1JCTZYqXyLW59ihVDfM6yX9LeixsxiO0JZlyZCQs" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FkXLVpTEowt-lS_-_Aog7QYBdydeA7I5PNrK-01QiGCIPJJOQeMRR9LvwGpeNzXzmR4wUrBda9OjDZbbVKcEDRiTYJzmpo6sj8bMu9DuIIsF_1cp1JCTZYqXyLW59ihVDfM6yX9LeixsxiO0JZlyZCQs" alt="A screenshot showing the Spaces Key tab" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, in the &lt;strong&gt;Spaces Key&lt;/strong&gt; section, click &lt;strong&gt;Generate New Token.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2F23Ws6ofo9coNsAqcr6dHrh3D1ulwW7cx312GpxQ4oz6DDB7Xp-z3es2nlug_V88QiAoNQyQgcpGs0CbXQqw63gcWNWt4u1Fuembfk2g9Ft0O7fdAfVXaNb99jqdgo5Hbo7a-io8n6NAd2nOhHDTQtSY" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2F23Ws6ofo9coNsAqcr6dHrh3D1ulwW7cx312GpxQ4oz6DDB7Xp-z3es2nlug_V88QiAoNQyQgcpGs0CbXQqw63gcWNWt4u1Fuembfk2g9Ft0O7fdAfVXaNb99jqdgo5Hbo7a-io8n6NAd2nOhHDTQtSY" alt="A screenshot of the Generate New Key button on the Spaces Key" width="1600" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter the name of the key, for this case, &lt;strong&gt;nuxt-media-gallery&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FiQ0vW6FwrwVPjLazbYRjGMnKOIcPNjzIGMQPeKXb7TX92GcWn8T27-zkRD0f2VDYrBDRn_uphojKxb4MLXJUvUjoobaD2aqZlQ6mDeL2B11ELRFT2o6zSLqTeWrvDfkTWYwp9JxfhVFSMcPAa6CNIO8" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FiQ0vW6FwrwVPjLazbYRjGMnKOIcPNjzIGMQPeKXb7TX92GcWn8T27-zkRD0f2VDYrBDRn_uphojKxb4MLXJUvUjoobaD2aqZlQ6mDeL2B11ELRFT2o6zSLqTeWrvDfkTWYwp9JxfhVFSMcPAa6CNIO8" alt="A screenshot showing the input to enter the name for your access keys" width="1600" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then click the button indicated below to generate the key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FsnwT-E-MkTzczJbbvgBt3trJjYfGn8aJDHItnmASTHF0EZqfzB6t3xcwtgCe1hqUeQqU7jUVBNZ03L9yWoI7GDgpTAJxUVGa-ptSmiacEznONwWScI196eToGClhVMZl3ij3Yz9v2gezyUuyhB2cyq4" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FsnwT-E-MkTzczJbbvgBt3trJjYfGn8aJDHItnmASTHF0EZqfzB6t3xcwtgCe1hqUeQqU7jUVBNZ03L9yWoI7GDgpTAJxUVGa-ptSmiacEznONwWScI196eToGClhVMZl3ij3Yz9v2gezyUuyhB2cyq4" alt="A screenshot showing the button to trigger generating the key" width="1600" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, you’ll have the &lt;strong&gt;access keys&lt;/strong&gt; and &lt;strong&gt;secret&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2FFJNYVpJnRJpFpvBHl1tevRj2yKDNKvvrjCsPCCPXjAdPQydU3lIR0J3A6JxpueFrXwCEohLwsSnfbLflkqXg6GWs78JID5MIGwf23X6IwPgzVqoxn7Nq8DCK4yBSP8xXbrdBCPrgkZ9NUOD-NJhK6lQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh4.googleusercontent.com%2FFJNYVpJnRJpFpvBHl1tevRj2yKDNKvvrjCsPCCPXjAdPQydU3lIR0J3A6JxpueFrXwCEohLwsSnfbLflkqXg6GWs78JID5MIGwf23X6IwPgzVqoxn7Nq8DCK4yBSP8xXbrdBCPrgkZ9NUOD-NJhK6lQ" alt="A screenshot showing the Access Key and Access Secret" width="1600" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Access Secret&lt;/strong&gt; is located in the &lt;strong&gt;Secret&lt;/strong&gt; row, and the &lt;strong&gt;Access Key&lt;/strong&gt; is located in the &lt;strong&gt;nuxt-media-gallery&lt;/strong&gt; row. Make a copy and save your Secret key because it will be lost if you leave the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Appwrite
&lt;/h2&gt;

&lt;p&gt;To proceed, you‘ll need to locally host your Appwrite server. Let’s use Docker to accomplish this. Check out the &lt;a href="https://appwrite.io/docs/self-hosting?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;installation guide&lt;/a&gt; to learn more about self-hosting Appwrite.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Locally hosting Appwrite with Docker&lt;/strong&gt;&lt;br&gt;
Ensure Docker is running by using the command below on your terminal to verify.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a directory named &lt;strong&gt;appwrite-spaces&lt;/strong&gt; in the current working directory using the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir appwrite-spaces 
cd appwrite-spaces
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, download the Appwrite base &lt;a href="https://appwrite.io/install/compose?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;docker-compose.yml&lt;/a&gt; and &lt;a href="https://appwrite.io/install/env?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;.env&lt;/a&gt; files into the created folder.&lt;/p&gt;

&lt;p&gt;Open the &lt;strong&gt;.env&lt;/strong&gt; file and update the keys' values as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_APP_STORAGE_DEVICE=DOSpaces
_APP_STORAGE_DO_SPACES_BUCKET=&amp;lt;bucket-name&amp;gt;
_APP_STORAGE_DO_SPACES_REGION=&amp;lt;bucket-region&amp;gt;
_APP_STORAGE_DO_SPACES_SECRET=&amp;lt;access-secret&amp;gt;
_APP_STORAGE_DO_SPACES_ACCESS_KEY=&amp;lt;access-key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Setting &lt;code&gt;_APP_STORAGE_DEVICE&lt;/code&gt; from &lt;code&gt;Local&lt;/code&gt; to &lt;code&gt;DOSpaces&lt;/code&gt; indicates to Appwrite to use DigitalOcean Spaces instead of a locally implemented storage system.&lt;/p&gt;

&lt;p&gt;Make sure you replace &lt;code&gt;&amp;lt;bucket-name&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;bucket-region&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;access-secret&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;access-key&amp;gt;&lt;/code&gt; (which are the keys obtained from the API section of the DigitalOcean dashboard).&lt;/p&gt;

&lt;p&gt;Once that is done, execute this command within the &lt;strong&gt;appwrite-spaces&lt;/strong&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up --remove-orphans -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;--remove-orphans&lt;/code&gt; flag will remove containers unrelated to the present services before initiating the new ones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FmBa5Vh7Ao_z5-OuhCAvvZF2j0LNDclVWegK0mMYo2WiW4H1I5eJreaO0mCz0PVqZO4D-nUjQ16Grf71U2L_MhD0wqY9iriIxQ7BzChC4e0-6lUqaX33uSagBv_bDE29Cuq2uh_t64ImWiRLrry_olJ0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2FmBa5Vh7Ao_z5-OuhCAvvZF2j0LNDclVWegK0mMYo2WiW4H1I5eJreaO0mCz0PVqZO4D-nUjQ16Grf71U2L_MhD0wqY9iriIxQ7BzChC4e0-6lUqaX33uSagBv_bDE29Cuq2uh_t64ImWiRLrry_olJ0" alt="A screenshot showing the executing Docker compose command" width="1600" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the services have been pulled by Docker from the Docker registry, the containers are then created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FmISW18bfkdBOpOb7ogKr6OWh_1tkxFG0pNfsoz5bGVzU7Uj2VpD7iidWQRP1ZZaXZisi49KFaJiVslAFdOCm40xUpS3sqiXygFAz6yMBcbK-6ScRZN039QXEgVI8MP3mwp-7MNU8MlRw-vp4z0TKUlo" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FmISW18bfkdBOpOb7ogKr6OWh_1tkxFG0pNfsoz5bGVzU7Uj2VpD7iidWQRP1ZZaXZisi49KFaJiVslAFdOCm40xUpS3sqiXygFAz6yMBcbK-6ScRZN039QXEgVI8MP3mwp-7MNU8MlRw-vp4z0TKUlo" alt="A screenshot showing the competed execution of the command" width="1600" height="1000"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, navigate to &lt;a href="http://localhost" rel="noopener noreferrer"&gt;http://localhost&lt;/a&gt; to access your Appwrite instance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdg88xp36l586y4nwcfr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdg88xp36l586y4nwcfr7.png" alt="A screenshot showing the landing page after visiting http://localhost" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, click &lt;strong&gt;Sign up&lt;/strong&gt; to create a new account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8wtnw33nrrdlge3fgox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8wtnw33nrrdlge3fgox.png" alt="A screenshot showing the sign up page" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After signing up, enter your project’s name. For this case, use &lt;strong&gt;nuxt-media-gallery&lt;/strong&gt; then click &lt;strong&gt;Create Project&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdgkdg1ujt66km0lgggmi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdgkdg1ujt66km0lgggmi.png" alt="A screenshot showing the section to enter the project’s name" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating the Appwrite storage for the project&lt;/strong&gt;&lt;br&gt;
To create the storage, Select &lt;strong&gt;Storage&lt;/strong&gt; and click &lt;strong&gt;Create bucket&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8cvtizh0agwl37jn2bk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8cvtizh0agwl37jn2bk.png" alt="A screenshot showing the Storage menu button and the Create Bucket button" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, enter the name of the bucket. In this case, use &lt;strong&gt;nuxt-media-bucket&lt;/strong&gt;, then click &lt;strong&gt;Create&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvw1xuhyiq42v0rm632qu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvw1xuhyiq42v0rm632qu.png" alt="A screenshot showing the name input and the create button" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Following that, you must grant &lt;strong&gt;CREATE&lt;/strong&gt; and &lt;strong&gt;READ&lt;/strong&gt; permissions to &lt;strong&gt;any&lt;/strong&gt; user on this storage bucket. To do so, click the &lt;strong&gt;Settings&lt;/strong&gt; tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fedznn7dameowxu7o86s0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fedznn7dameowxu7o86s0.png" alt="A screenshot showing the settings tab" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, navigate to the &lt;strong&gt;Permissions&lt;/strong&gt; section, click &lt;strong&gt;Add a role to get started&lt;/strong&gt; and select the &lt;strong&gt;Any&lt;/strong&gt; option.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8v5ebotngg0ozswd0nd3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8v5ebotngg0ozswd0nd3.png" alt="A screenshot showing the Add a role to get started button" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, select the &lt;strong&gt;CREATE&lt;/strong&gt; and &lt;strong&gt;READ&lt;/strong&gt; permissions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa44p4jakzzbl5c4tk039.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa44p4jakzzbl5c4tk039.png" alt="A screenshot showing the CREATE and READ checkbox" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extracting your Appwrite credentials&lt;/strong&gt;&lt;br&gt;
To retrieve your credentials, you need to get the values for the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;appwrite-bucket-id&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;appwrite-project-id&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;appwrite-api-endpoint&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Navigate to &lt;strong&gt;Settings&lt;/strong&gt; by clicking the &lt;strong&gt;Settings menu&lt;/strong&gt; to obtain the &lt;code&gt;&amp;lt;appwrite-project-id&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgr6rzrnkj8xfkec9mbrs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgr6rzrnkj8xfkec9mbrs.png" alt="A screenshot showing the Settings menu" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, find the &lt;strong&gt;Project ID&lt;/strong&gt; and &lt;strong&gt;API Endpoint&lt;/strong&gt; as indicated below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fni39rebrl7gis0mln1o0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fni39rebrl7gis0mln1o0.png" alt="A screenshot showing the Project ID and the API Endpoint" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, to get the &lt;strong&gt;bucket ID&lt;/strong&gt;, navigate to the &lt;strong&gt;Storage&lt;/strong&gt; menu; there, you’ll see the &lt;strong&gt;bucket ID&lt;/strong&gt; on the bucket as indicated below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flagcmhp0b9x2wrsgwnm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flagcmhp0b9x2wrsgwnm7.png" alt="A screenshot showing the BucketID" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up the Nuxt.js project
&lt;/h2&gt;

&lt;p&gt;To set up the Nuxt.js project, open your terminal, and run the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx nuxi@latest init &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, replace the &lt;code&gt;&amp;lt;project-name&amp;gt;&lt;/code&gt; with &lt;code&gt;nuxt-media-gallery&lt;/code&gt;. Then run the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This changes the current working directory of the terminal to the project’s directory. Next, you’ll need to install all the dependencies.&lt;/p&gt;

&lt;p&gt;The dependencies for this project include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs/sdks" rel="noopener noreferrer"&gt;Appwrite SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://swiperjs.com/" rel="noopener noreferrer"&gt;Swiperjs&lt;/a&gt; (this will be used to perform the slide show)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To install, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add appwrite swiper @nuxtjs/tailwindcss @vueuse/core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the steps &lt;a href="https://tailwindcss.nuxtjs.org/getting-started/setup" rel="noopener noreferrer"&gt;here&lt;/a&gt; to set up &lt;strong&gt;TailwindCSS&lt;/strong&gt; for the project.&lt;br&gt;
After that, create an &lt;strong&gt;assets&lt;/strong&gt; folder in the root directory and add the folders and files according to this &lt;a href="https://github.com/Otrex/nuxt-media-gallary/tree/main/assets" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding the environmental variable&lt;/strong&gt;&lt;br&gt;
To add these variables, create a &lt;strong&gt;.env&lt;/strong&gt; file in the root directory of the project and add the following to the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NUXT_APPWRITE_API_ENDPOINT=&amp;lt;appwrite-api-endpoint&amp;gt;
NUXT_APPWRITE_BUCKET_ID=&amp;lt;appwrite-bucket-id&amp;gt;
NUXT_APPWRITE_PROJECT_ID=&amp;lt;appwrite-project-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;&amp;lt;appwrite-api-endpoint&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;appwrite-bucket-id&amp;gt;&lt;/code&gt;, and &lt;code&gt;&amp;lt;appwrite-project-id&amp;gt;&lt;/code&gt; values with the values you obtained from the Appwrite dashboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating the UI components and screens&lt;/strong&gt;&lt;br&gt;
To do so, first add the &lt;strong&gt;pages&lt;/strong&gt; folder to the project's root directory. This is required for creating the application's &lt;strong&gt;routes/screens&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Next, navigate to the &lt;strong&gt;app.vue&lt;/strong&gt; file and change the file's content to look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-screen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;nuxt-page&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;swiper/css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Landing screen&lt;/strong&gt;&lt;br&gt;
Following that, create a screen to collect the user's name so that the media files can be saved and identified.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;pages&lt;/strong&gt; folder, create a file, &lt;strong&gt;index.vue,&lt;/strong&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"x-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"x-card"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Welcome to MShare&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt;Please provide your name so we can setup your unique profile&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
          &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
          &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full"&lt;/span&gt;
          &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"store.name"&lt;/span&gt;
          &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Name: e.g. Obisike Treasure"&lt;/span&gt;
        &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mt-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
          &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt;
          &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"navigateTo('/gallery')"&lt;/span&gt;
          &lt;span class="na"&gt;:disabled=&lt;/span&gt;&lt;span class="s"&gt;"!!!store.name"&lt;/span&gt;
          &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full bg-orange-400 disabled:bg-orange-200 disabled:text-gray-600"&lt;/span&gt;
          &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"Create"&lt;/span&gt;
        &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAppSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The vue template above consists of a card-like UI element with the heading "Welcome to MShare" and a paragraph prompting users to provide their name to create their gallery. Two input elements are present: one for the user's name and another for a "Create" button. The button is disabled until the user enters their name and then changes color. When users enter their name and click the button, the "create" method is triggered, allowing them to continue with the gallery creation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gallery screen&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Following that, you need to add the &lt;strong&gt;route/screen&lt;/strong&gt; for the users to upload their gallery. To do this, create a file &lt;strong&gt;gallery.vue&lt;/strong&gt; in the &lt;strong&gt;pages&lt;/strong&gt; directory, then add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-screen p-[3rem]"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"x-card !max-w-full"&lt;/span&gt; &lt;span class="na"&gt;v-if=&lt;/span&gt;&lt;span class="s"&gt;"store.previewKey"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
      &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt; Sharable Link: 
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-slate-200 inline-block px-2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; {{ location?.origin }}/share/{{ store.previewKey }} &lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"x-card !max-w-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
      &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt; Select your media file:&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"x-card !max-w-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"grid grid-cols-2 sm:grid-cols-4 gap-[2rem]"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;transition-group&lt;/span&gt; &lt;span class="na"&gt;appear&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"fade"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
          &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full aspect-square x-border"&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"(img, idx) in images"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"img.idx"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full h-full relative"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"img.url"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full h-full object-cover"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"absolute inset-0 backdrop:bg-slate-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-white rounded-md m-3 px-3"&lt;/span&gt; &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"removeImage(idx)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Remove&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/transition-group&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full aspect-square"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
          &lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"x-input__file w-full h-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"48"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 -960 960 960"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"48"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;path&lt;/span&gt; &lt;span class="na"&gt;d=&lt;/span&gt;&lt;span class="s"&gt;"M450-450H200v-60h250v-250h60v250h250v60H510v250h-60v-250Z"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;p&amp;gt;&lt;/span&gt; Add Image&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
              &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"file"&lt;/span&gt;
              &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"imageField"&lt;/span&gt;
              &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;change=&lt;/span&gt;&lt;span class="s"&gt;"setImages"&lt;/span&gt;
              &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"images"&lt;/span&gt;
              &lt;span class="na"&gt;multiple&lt;/span&gt;
              &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt;
              &lt;span class="na"&gt;accept=&lt;/span&gt;&lt;span class="s"&gt;"image/*"&lt;/span&gt;
            &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"x-card !max-w-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
      &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; 
        &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bg-orange-300 disabled:bg-orange-100 w-full py-[1rem]"&lt;/span&gt; 
        &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;click=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; 
        &lt;span class="na"&gt;:disabled=&lt;/span&gt;&lt;span class="s"&gt;"!images?.length"&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ loading ? 'Uploading...': 'Upload' }}&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The template above consists of a container with multiple cards and grids. The first card displays a sharable link if the &lt;code&gt;store.reviewKey&lt;/code&gt; data exists. The second and third cards show static content. The fourth card contains a grid with images that can be added or removed using a &lt;strong&gt;Remove&lt;/strong&gt; button. Users can upload multiple images using a hidden file input, and an &lt;strong&gt;Upload&lt;/strong&gt; button is disabled until images are selected.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;appwrite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IFileImage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;utils&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRuntimeConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAppSession&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;location&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Location&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;IFileImage&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;removeImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;splice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;setImages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HTMLInputElement&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fileImages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;convertToURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
      &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="nx"&gt;idx&lt;/span&gt;
    &lt;span class="p"&gt;})),&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;fileImages&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;pushToAppwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;previewKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Successfully published!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pushToAppwrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;File&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;appwriteStorage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appwriteBucketId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;custom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;generateKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nx"&gt;file&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the provided script, the &lt;code&gt;pushToAppwrite()&lt;/code&gt; function connects to Appwrite using credentials and uploads a given file object. A unique key is generated using &lt;code&gt;generateKey()&lt;/code&gt; for future file retrieval.&lt;br&gt;
The &lt;code&gt;setImages()&lt;/code&gt; function extracts images from the file input and creates a base64 URL with &lt;code&gt;convertToURL()&lt;/code&gt;. This URL is then used to render the file blob as an image URL in a grid block.&lt;br&gt;
The &lt;code&gt;submit()&lt;/code&gt; function uploads images using &lt;code&gt;setImages()&lt;/code&gt; to the &lt;code&gt;images&lt;/code&gt; state. It also generates a &lt;code&gt;previewKey&lt;/code&gt; for creating a shareable URL. To retrieve files with the shareable ID, the file ID has to be in this format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&amp;lt;name&amp;gt;-&amp;lt;timestamp&amp;gt;-&amp;lt;length-of-array-of-images&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Share screen&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, create the screen for the shareable link. Begin by creating a folder, &lt;strong&gt;share&lt;/strong&gt;, within the &lt;strong&gt;pages&lt;/strong&gt; directory. Inside the &lt;strong&gt;share&lt;/strong&gt; folder, create a file called &lt;strong&gt;[pid].vue&lt;/strong&gt;.&lt;br&gt;
As per Nuxt guidelines, the route path is &lt;strong&gt;/share/[pid]&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then, append the specified content to the &lt;strong&gt;[pid].vue&lt;/strong&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;template&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"py-[10%] px-[15%] w-full h-screen"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    {{ route.params }}
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"flex flex-col w-full h-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"x-card !max-w-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;h3&amp;gt;&lt;/span&gt; Obisike's Slideshows &lt;span class="nt"&gt;&amp;lt;/h3&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pb-20"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; 
        &lt;span class="nt"&gt;&amp;lt;swiper&lt;/span&gt;
          &lt;span class="na"&gt;:effect=&lt;/span&gt;&lt;span class="s"&gt;"'cards'"&lt;/span&gt;
          &lt;span class="na"&gt;:grabCursor=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;
          &lt;span class="na"&gt;:autoplay=&lt;/span&gt;&lt;span class="s"&gt;"{
            delay: 2500,
            disableOnInteraction: true,
          }"&lt;/span&gt;
          &lt;span class="na"&gt;:modules=&lt;/span&gt;&lt;span class="s"&gt;"modules"&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;template&lt;/span&gt; &lt;span class="na"&gt;v-for=&lt;/span&gt;&lt;span class="s"&gt;"(img, idx) in images"&lt;/span&gt; &lt;span class="na"&gt;:key=&lt;/span&gt;&lt;span class="s"&gt;"idx"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;swiper-slide&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"h-[20rem]"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;:src=&lt;/span&gt;&lt;span class="s"&gt;"img"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"w-full object-cover"&lt;/span&gt; &lt;span class="na"&gt;loading=&lt;/span&gt;&lt;span class="s"&gt;"lazy"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/swiper-slide&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/swiper&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;style &lt;/span&gt;&lt;span class="na"&gt;scoped&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.swiper-cards&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.swiper-cards&lt;/span&gt; &lt;span class="nc"&gt;.swiper-slide&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;transform-origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;center&lt;/span&gt; &lt;span class="nb"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;-webkit-backface-visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;backface-visibility&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;overflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The template creates a slideshow using the &lt;strong&gt;Swiper&lt;/strong&gt; library. It arranges images in a card-style layout, with a title given by the name of the gallery’s creator together with &lt;strong&gt;SlideShow&lt;/strong&gt;, above the slideshow. The images transition using a &lt;strong&gt;cards&lt;/strong&gt; effect and autoplay every 2.5 seconds. The template ensures responsiveness and lazy loading for images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;setup&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"ts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Swiper&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SwiperSlide&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;swiper/vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EffectCards&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Autoplay&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;swiper/modules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;modules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;Autoplay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EffectCards&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRuntimeConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRoute&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;span class="nf"&gt;onMounted&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;getImages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getImages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;appwriteStorage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getFileIdsFromPreviewKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFileView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appwriteBucketId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To break it down, in the script above, when the component loads, a function is triggered to fetch images, and then the &lt;code&gt;getImage()&lt;/code&gt; function gets the image from Appwrite using the route parameter &lt;code&gt;pid&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Additional modules, Autoplay and EffectCards, are applied to the Swiper component to enhance the slideshow with a card-stacking effect.&lt;/p&gt;

&lt;p&gt;Next, you’ll need to add the utility functions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adding the utilities functions&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To add utility functions, create a folder &lt;strong&gt;utils&lt;/strong&gt; and a file &lt;strong&gt;index.ts&lt;/strong&gt; within the &lt;strong&gt;utils&lt;/strong&gt; folder. Then copy the contents of &lt;a href="https://github.com/Otrex/nuxt-media-gallary/blob/main/utils/index.ts" rel="noopener noreferrer"&gt;this file&lt;/a&gt; and paste them into the &lt;strong&gt;index.ts&lt;/strong&gt; file.&lt;br&gt;
The functions in this file is automatically imported due to Nuxt.js. &lt;/p&gt;

&lt;p&gt;One of the notable functions you copied is the &lt;code&gt;appwriteStorage()&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;appwriteStorage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRuntimeConfig&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Storage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;client&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEndpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appwriteAPIEndpoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kr"&gt;public&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appwriteProjectId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;storage&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function obtains the environment variable via &lt;code&gt;useRuntimeConfig()&lt;/code&gt;, establishes a connection to Appwrite Storage service, and returns the storage object, which contains methods for retrieving and uploading files to appwrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application demo
&lt;/h2&gt;

&lt;p&gt;To showcase your application, start by accessing your terminal within the project directory, then execute the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the command is successfully executed, the Nuxt.js development server will start on the port 3000.&lt;/p&gt;

&lt;p&gt;Visit &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; on the browser to preview the screens. &lt;/p&gt;

&lt;p&gt;Next, enter your desired name then click &lt;strong&gt;Create.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2Fc_2zngPA_upj7QN9CVHU6W-Yxal9cIqjQoo9ewis1cU9YJKtXks4MhwTmF80ZQBCQ8Ivu6S-KlsLZ1tkLBCab489KKPDsKpDpDcoRms42UMRQ-NkHgv99o9jt3NV35e5tSA5y8CiNxTGdDFKptF-q18" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2Fc_2zngPA_upj7QN9CVHU6W-Yxal9cIqjQoo9ewis1cU9YJKtXks4MhwTmF80ZQBCQ8Ivu6S-KlsLZ1tkLBCab489KKPDsKpDpDcoRms42UMRQ-NkHgv99o9jt3NV35e5tSA5y8CiNxTGdDFKptF-q18" alt="A screenshot showing the entry point of the application" width="1600" height="921"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, click &lt;strong&gt;Add Image&lt;/strong&gt;, to add the images.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FQM4tU4ZCjORTZ-VAkTmuPLbD9_ZyKKyR4LclBo-Qnvmc1FsyTT9qepKwoDSGM8x4MzO104eESXjTfqqreRZ04zFru3mpbFxU5LMDzZwQfUwDx8b3dWfJbzjjI8kQ8ExGZAu2nBjydu9THgglKXcZ72Q" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh5.googleusercontent.com%2FQM4tU4ZCjORTZ-VAkTmuPLbD9_ZyKKyR4LclBo-Qnvmc1FsyTT9qepKwoDSGM8x4MzO104eESXjTfqqreRZ04zFru3mpbFxU5LMDzZwQfUwDx8b3dWfJbzjjI8kQ8ExGZAu2nBjydu9THgglKXcZ72Q" alt="A screenshot showing the add images screen" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then click &lt;strong&gt;Upload&lt;/strong&gt; to upload the selected images. &lt;br&gt;
Once that is done, a shareable link will be generated. Copy and open this link in a different browser window.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FZaGsYpDXfAKL2rrHzQ_6fyS5f_zM28p9wOTOBI5cOg3_az8SqN-IP49VrLwF5Uz714Ne0IBvJTaxCgIz-vt2CvqoJU04_M1UCRavk0thFGUQRBYpfLDyW5RZwIDUqipTNZ9V8aeuhdYwQy9vt-BnY3Y" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh6.googleusercontent.com%2FZaGsYpDXfAKL2rrHzQ_6fyS5f_zM28p9wOTOBI5cOg3_az8SqN-IP49VrLwF5Uz714Ne0IBvJTaxCgIz-vt2CvqoJU04_M1UCRavk0thFGUQRBYpfLDyW5RZwIDUqipTNZ9V8aeuhdYwQy9vt-BnY3Y" alt="A screenshot showing the shared gallery" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a video showcasing the application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.loom.com/share/0aac3ddd749748ad915b0f438837c6f6?sid=1daab281-7f22-40d4-ba9d-04cc45251084" rel="noopener noreferrer"&gt;https://www.loom.com/share/0aac3ddd749748ad915b0f438837c6f6?sid=1daab281-7f22-40d4-ba9d-04cc45251084&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To prove that the files are uploaded to Digital Oceans directly, here is a screenshot showing the file on Digital Oceans’ spaces.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhiy4fhw6wu7ut5c2422q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhiy4fhw6wu7ut5c2422q.png" alt="a screenshot showing the file on Digital Oceans’ spaces" width="800" height="493"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we've learned how to extend Appwrite's storage capabilities using DigitalOcean Spaces. By combining the strengths of these two services, developers can create robust applications with secure and scalable storage solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/appwrite/scale-appwrite-storage-with-digitalocean-spaces-36kh"&gt;Scale Appwrite Storage with DigitalOcean Spaces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nuxt.com/docs" rel="noopener noreferrer"&gt;Nuxt.js Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Appwrite Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>appwriteself</category>
      <category>nuxt</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to create a Docker Swarm of Appwrite and Swarmpit containers</title>
      <dc:creator>Obisike Treasure</dc:creator>
      <pubDate>Fri, 07 Jul 2023 07:33:52 +0000</pubDate>
      <link>https://dev.to/hackmamba/how-to-create-a-docker-swarm-of-appwrite-containers-and-ui-with-swarmpit-1nje</link>
      <guid>https://dev.to/hackmamba/how-to-create-a-docker-swarm-of-appwrite-containers-and-ui-with-swarmpit-1nje</guid>
      <description>&lt;p&gt;The demand for efficient and scalable infrastructure management has never been greater in today's dynamic software development landscape. Some of the best tools for this landscape are &lt;a href="https://docs.docker.com/engine/swarm/" rel="noopener noreferrer"&gt;Docker Swarm&lt;/a&gt;, &lt;a href="https://appwrite.io/?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Appwrite&lt;/a&gt;, and &lt;a href="https://swarmpit.io/?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Swarmpit&lt;/a&gt;, which provide high flexibility and performance.&lt;/p&gt;

&lt;p&gt;By leveraging the capabilities of these technologies, organizations can achieve increased scalability, reliability, and productivity in their application deployment and management processes. These technologies facilitate seamless containerization, faster development with pre-built services, and easier cluster administration.&lt;/p&gt;

&lt;p&gt;In this tutorial, you'll learn how to deploy your Appwrite containers using Docker Swarm and manage the containers using Swarmpit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To get the most out of this tutorial, ensure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;An &lt;a href="https://en.wikipedia.org/wiki/ARM_architecture_family" rel="noopener noreferrer"&gt;ARM&lt;/a&gt;-based personal computer, such as the M1 MacBook&lt;/li&gt;
&lt;li&gt;Terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Set up the virtual machine servers
&lt;/h2&gt;

&lt;p&gt;First, you’ll be setting up two virtual machines, &lt;strong&gt;Manager&lt;/strong&gt; and &lt;strong&gt;Worker&lt;/strong&gt;, which will act as the servers for our swarm. To proceed, do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download and Install the UTM virtualizer from the official &lt;a href="https://mac.getutm.app/" rel="noopener noreferrer"&gt;website&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Download the Ubuntu server 22.04.2 LTS for ARM from their official &lt;a href="https://ubuntu.com/download/server/arm" rel="noopener noreferrer"&gt;website&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After that, follow the instructions in this &lt;a href="https://docs.getutm.app/guides/ubuntu/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; to install the Ubuntu server on the virtual machines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mp1scer8ass5puj6po3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5mp1scer8ass5puj6po3.png" alt="A screenshot showing the servers created" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During the Ubuntu server installation, you will have the opportunity to install Docker and OpenSSH. It is recommended that you select both of these options during the installation process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9533dej3e5yi4nwp97yj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9533dej3e5yi4nwp97yj.png" alt="A screenshot showing the manager server and the worker server" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have completed the installation, you can verify the installation of Docker and OpenSSH. To check the Docker version, run the following command in the terminal:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker -v
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If Docker fails to install during the Ubuntu installation, you can refer to the &lt;a href="https://docs.docker.com/engine/install/ubuntu/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for installation instructions.&lt;/p&gt;

&lt;p&gt;For OpenSSH, you can check the SSH service status by executing the command below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl status sshd.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once you've completed that, execute the following command to install Git:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Set up the network file system (NFS) mount
&lt;/h2&gt;

&lt;p&gt;The NFS mount enables the sharing of a directory. As the service needs to be deployed across multiple nodes, it is crucial to share certain resources, such as volumes, across all nodes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Accessing the&lt;/strong&gt; &lt;strong&gt;n&lt;/strong&gt;&lt;strong&gt;odes&lt;/strong&gt; &lt;strong&gt;v&lt;/strong&gt;&lt;strong&gt;ia SSH&lt;/strong&gt;&lt;br&gt;
To ensure smooth server access, start by retrieving the IP address for the servers using the following command:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ip addr | grep “inet 192”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkw4g32s9kdmozy8zzr9w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkw4g32s9kdmozy8zzr9w.png" alt="A screenshot showing the IP address of the worker" width="800" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll need to repeat the steps to retrieve the IP addresses for both the manager and worker nodes.&lt;/p&gt;

&lt;p&gt;Once you have obtained both the manager and worker IP addresses, follow these instructions to SSH into the servers from the virtual machine host computer.&lt;/p&gt;

&lt;p&gt;Open two terminal sessions on the virtual machine host computer; in the first terminal, execute the following command to connect to the manager server:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh manager@&amp;lt;manager_ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For the  second terminal, run the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh worker@&amp;lt;worker_ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This connects to the worker server.&lt;br&gt;
Replace both &lt;code&gt;&amp;lt;manager_ip&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;worker_ip&amp;gt;&lt;/code&gt; with their corresponding IP addresses.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs3hmj3cdv1nm3cjfgrsm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs3hmj3cdv1nm3cjfgrsm.png" alt="A screenshot showing the successful SSH into the manager and worker node" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting up the NFS&lt;/strong&gt;&lt;br&gt;
Next, you can follow these steps to set up the NFS shared directory on the manager's SSH terminal.&lt;br&gt;
First, install the NFS server package on the host by executing the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install nfs-kernel-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After installing the NFS server package, you need to create the shared directory on the host using the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir ./nfs/app -p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To ensure security, NFS converts any root actions performed on the &lt;code&gt;worker&lt;/code&gt; (client) to the &lt;code&gt;nobody:nogroup&lt;/code&gt; credentials. To align the directory ownership with these credentials, you need to execute the following command on the manager node terminal:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo chown nobody:nogroup ./nfs/app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Afterward, open the &lt;code&gt;/etc/exports&lt;/code&gt; file on the host machine with root privileges:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/exports
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Within the &lt;code&gt;/etc/exports&lt;/code&gt; file, create a configuration line for each directory you want to share. Replace &lt;strong&gt;&lt;/strong&gt; with the actual IP address of the worker node. For example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/home/manager/nfs/app    &amp;lt;worker_ip&amp;gt;(rw,sync,no_subtree_check)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this configuration line, the &lt;code&gt;rw&lt;/code&gt; option grants read and write access to the client, &lt;code&gt;sync&lt;/code&gt; ensures changes are written to disk before replying, and &lt;code&gt;no_subtree_check&lt;/code&gt; disables subtree checking to prevent issues when files are renamed while open on the client.&lt;/p&gt;

&lt;p&gt;Save and close the &lt;code&gt;/etc/exports&lt;/code&gt; file. &lt;br&gt;
Finally, restart the NFS server to make the shares available:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart nfs-kernel-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If you have a firewall, you must adjust the settings to allow the worker node to access the files.&lt;/p&gt;

&lt;p&gt;After that, you have to mount this directory on the worker node. To do this, Firstly, install the nfs-common on the worker node using the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install nfs-common
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then create mount the directory using the following commands:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir -p /nfs/app
sudo mount &amp;lt;manager_ip&amp;gt;:/home/manager/nfs/app /nfs/app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Replace &lt;code&gt;&amp;lt;manager_ip&amp;gt;&lt;/code&gt; with the actual &lt;strong&gt;manager&lt;/strong&gt; IP. Once that is done, you can run this command to check that the NFS shared directory has been mounted.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df -h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvdzlwqyb10j65xikrxc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvdzlwqyb10j65xikrxc.png" alt="A screenshot showing the mounted shared directory" width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the swarm
&lt;/h2&gt;

&lt;p&gt;Docker Swarm provides a native clustering and orchestration solution for Docker, enabling efficient distribution and scalability of services across multiple nodes.&lt;/p&gt;

&lt;p&gt;To initiate Docker Swarm on the manager node, execute the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker swarm init --advertise-addr &amp;lt;manager_ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By running this command specifically on the manager node, Docker Swarm is activated, and a &lt;strong&gt;join token&lt;/strong&gt; is generated. This token allows for creating and managing a swarm of Docker worker nodes, empowering you to scale and distribute services seamlessly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73jf8bg8g8wex4rx47fr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73jf8bg8g8wex4rx47fr.png" alt="A screenshot showing the join token and the join command" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the command and run it on the worker node to join the worker node to the swarm.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvirdj9vngobcy7w2gdlu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvirdj9vngobcy7w2gdlu.png" alt="A screenshot showing that the worker node has joined the swarm" width="800" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once this is successful, you can check whether the node has been added to the swarm on the manager node by running the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker node ls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafd7s1ewykmsmp11gafb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafd7s1ewykmsmp11gafb.png" alt="A screenshot showing the nodes" width="800" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating and deploying the Appwrite services on the swarm
&lt;/h2&gt;

&lt;p&gt;To do this, you’ll be using the &lt;code&gt;docker&lt;/code&gt; &lt;code&gt;stack&lt;/code&gt; command. This command allows you to set up multiple Docker services via the compose file. It uses the YAML file to set up its services.&lt;br&gt;
First, you must download the appwrite &lt;code&gt;docker-compose.yml&lt;/code&gt; from the Appwrite’s &lt;a href="https://appwrite.io/docs/self-hosting#manual" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and modify its content to be swarm-compatible.&lt;/p&gt;

&lt;p&gt;After downloading the file, you can open it using any text editor you prefer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preparing the Appwrite swarm file&lt;/strong&gt;&lt;br&gt;
To proceed, use the shared directories as volumes, as Docker Swarm does not typically share volumes between nodes. Using the previously created NFS directory, you can easily share directories between nodes. &lt;/p&gt;

&lt;p&gt;To make it happen, you must take the following steps: &lt;/p&gt;

&lt;p&gt;On your manager node, run the following commands.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd ./nfs/app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This step is crucial because the compose file relies on specific files from this repository. Afterwards, you can create the necessary volume directories by executing the following command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p ./appwrite/{mariadb,redis,cache,uploads,certificates,functions,influxdb,config,builds,app,src,dev,docs,tests,public,appwrite} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After creating the volume directories, proceed to update the volumes in the downloaded compose file by deleting the volume specifications in the file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5p9bbp4zbfr5oqk6bgkc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5p9bbp4zbfr5oqk6bgkc.png" alt="A screenshot showing the volumes specification to be deleted" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, replace the volume specification of each service with their corresponding shared directory volume as indicated in the table below:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Old&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;New&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;appwrite-config:/storage/config:ro&lt;/td&gt;
&lt;td&gt;./appwrite/config:/storage/config:ro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;appwrite-certificates:/storage/certificates:ro&lt;/td&gt;
&lt;td&gt;./appwrite/certificates:/storage/certificates:ro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;appwrite-uploads:/storage/uploads:rw&lt;/td&gt;
&lt;td&gt;./appwrite/uploads:/storage/uploads:rw&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;appwrite-cache:/storage/cache:rw&lt;/td&gt;
&lt;td&gt;./appwrite/cache:/storage/cache:rw&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;appwrite-certificates:/storage/certificates:rw&lt;/td&gt;
&lt;td&gt;./appwrite/certificates:/storage/certificates:rw&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;appwrite-functions:/storage/functions:rw&lt;/td&gt;
&lt;td&gt;./appwrite/functions:/storage/functions:rw&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Next, to optimize request handling and resource allocation in a Docker Swarm cluster, restrict the &lt;code&gt;Traefik&lt;/code&gt; service to the manager node. Restricting this centralizes routing and load balancing, avoiding conflicts and simplifying management. &lt;/p&gt;

&lt;p&gt;Add the following configuration below the &lt;code&gt;Traefik&lt;/code&gt; service's port specification to enforce this restriction.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deploy:
      replicas: 1
      placement:
        constraints:
          - "node.role==manager"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The deploy option specifies that only one replica be created, and the service be deployed on the manager node.&lt;/p&gt;

&lt;p&gt;Afterward, it is necessary to include the environment variables. Typically, you need to specify the values for each service's environment variable individually. However, in this case, you can simplify the process by using an environment file containing all the required services' secrets. Simply add this file to each service requiring environment variables by adding the following specification.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env_file:
      - .env.appwrite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next, eliminate any unnecessary specifications in the file to ensure Swarm compatibility. Remove specifications such as &lt;code&gt;x-logging&lt;/code&gt; and &lt;code&gt;container-name&lt;/code&gt;, as they are incompatible with Swarm. Additionally, remove all occurrences of &lt;code&gt;&amp;lt;&amp;lt;: *x-logging&lt;/code&gt; from the compose file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdus45qvegg2ptxvdrstg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdus45qvegg2ptxvdrstg.png" alt="A screenshot showing the x-logging specification." width="800" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The docker-compose file should now look like this&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating the swarm file on the manager node&lt;/strong&gt;&lt;br&gt;
Once completed, you must copy the compose file to the manager node for deployment. To accomplish this, follow these steps.&lt;/p&gt;

&lt;p&gt;First, on the manager node, run the command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /home/manager/nfs/app/appwrite.swarm.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then copy the already modified file content from your text editor and paste it into the manager node’s nano editor interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2hzjgganluittoqjh68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp2hzjgganluittoqjh68.png" alt="A screenshot showing the pasted compose file on the manager node" width="800" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save the file. &lt;/p&gt;

&lt;p&gt;Next, run the following command.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /home/manager/nfs/app/.env.appwrite
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;After doing so, add this &lt;a href="https://github.com/Otrex/hackmamba-docker-swarm/blob/main/.env.appwrite" rel="noopener noreferrer"&gt;content&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you have completed all the previous steps, execute the following command on the manager's node to deploy the services:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker stack deploy -c /home/manager/nfs/app/appwrite.swarm.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This command initiates deploying the services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ymbyqzfj54yf0hp0djo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ymbyqzfj54yf0hp0djo.png" alt="A screenshot showing the services deploying" width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The deployment takes a while, as the docker stack command pulls the images from the Docker Hub before running the containers.&lt;/p&gt;

&lt;p&gt;To list all services, execute:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker service ls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For more detailed information about a specific service, use:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo docker service ps —no-trunc &amp;lt;SERVICE_NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;These commands provide valuable insights into the status and details of the services running within the Docker Swarm cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff12wog0cabdp9cssm637.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff12wog0cabdp9cssm637.png" alt="A screenshot showing the Appwrite services" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the services are up and running, open the web browser on the virtual machine’s host computer and visit &lt;code&gt;http://&amp;lt;manager_ip&amp;gt;&lt;/code&gt; to preview the Appwrite app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pzjqyg5mmiag61wizwv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6pzjqyg5mmiag61wizwv.jpg" alt="A screenshot showing the appwrite login page" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create and deploy the Swarmpit Services on the Swarm
&lt;/h2&gt;

&lt;p&gt;Once Appwrite has been successfully deployed, you can then proceed to set up the Swarmpit on the swarm. &lt;/p&gt;

&lt;p&gt;To deploy Swarmpit, run the following command on the manager node:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo git clone https://github.com/swarmpit/swarmpit -b master &amp;amp;&amp;amp; \
sudo docker stack deploy -c swarmpit/docker-compose.arm.yml swarmpit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakqb3o15dtgmy78uoyy3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakqb3o15dtgmy78uoyy3.png" alt="A screenshot showing the swarmpit services being created" width="800" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the swarmpit services have been deployed, navigate to the VM’s host browser, then visit &lt;a href="http://192.168.64.12:888" rel="noopener noreferrer"&gt;http://192.168.64.12:888&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fced3gcsp7gu7490oj6lu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fced3gcsp7gu7490oj6lu.png" alt="A screenshot showing swarmpit" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Managing the swarm with swarmpit
&lt;/h2&gt;

&lt;p&gt;To proceed, create your first admin account on Swarmpit by entering your username and password, then click &lt;strong&gt;Create Admin&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8nuyrasr4nd3fo2rqh5a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8nuyrasr4nd3fo2rqh5a.png" alt="A screenshot showing the entered username and password" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating your account, the browser will take you to the dashboard where you can manage the deployed services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70l4cp4foh4xk6td81oi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70l4cp4foh4xk6td81oi.png" alt="A screenshot showing the swarmpit interface" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Docker Swarm and Swarmpit provide numerous benefits when serving Appwrite. These tools enable rapid and efficient infrastructure setup and management. Swarmpit distinguishes itself by offering a user-friendly graphical interface in addition to swarm management capabilities.&lt;br&gt;
Furthermore, you can gain numerous advantages for your Appwrite applications by leveraging the power of Docker Swarm and Swarmpit. Scalability, high availability, simplified updates, service discovery, load balancing, and centralized control are just a few examples. &lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;You may find the following resources useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://help.ubuntu.com/" rel="noopener noreferrer"&gt;Ubuntu documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/" rel="noopener noreferrer"&gt;Docker documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://swarmpit.io/?utm_source=hackmamba&amp;amp;utm_medium=hackmamba-blog" rel="noopener noreferrer"&gt;Swarmpit documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hackmamba.io/blog/2022/04/deploy-and-host-an-appwrite-docker-application/" rel="noopener noreferrer"&gt;Deploying and hosting an Appwrite Docker Application&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>architecture</category>
      <category>docker</category>
      <category>swarmpit</category>
    </item>
    <item>
      <title>Custom OTP input component with VueJS</title>
      <dc:creator>Obisike Treasure</dc:creator>
      <pubDate>Mon, 13 Jun 2022 21:25:59 +0000</pubDate>
      <link>https://dev.to/otrex/custom-otp-input-component-with-vuejs-54dl</link>
      <guid>https://dev.to/otrex/custom-otp-input-component-with-vuejs-54dl</guid>
      <description>&lt;p&gt;Sometimes we may not be able to find the components we require to build our projects on the NPM package manager, and sometimes we may find one that does not work either on production or even during development. &lt;br&gt;
Here is when an expertise on building your very own component comes into play.&lt;br&gt;
In the very short tutorial, I would be going through how to build your very own custom VueJS OTP input component with ease.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Requirement&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VS Code editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To build this, we would first have to set up our project. In this tutorial, i would be using&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx -p @vue/cli vue create my-otp-project&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;to set up the vue project, selecting vue 2 as my preferred option.&lt;/p&gt;

&lt;p&gt;After the project has been setup correctly, we then access the folder of our already initialized project with our vscode editor. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F152itju07zkrdwkeeyjt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F152itju07zkrdwkeeyjt.png" alt="Image description" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We locate the &lt;code&gt;App.vue&lt;/code&gt; file and open it. Remove the content of the &lt;code&gt;&amp;lt;div id="app"&amp;gt;&lt;/code&gt;, that is were the OTPcomponent would be added.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw9dmv28zgdjdoijglze.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcw9dmv28zgdjdoijglze.png" alt="Image description" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then we create a new component file with the name &lt;code&gt;OTPInput.vue&lt;/code&gt;. this is were our code is going to be in.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/components/OTPInput.vue&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;!-- Vue template code here --&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  // Vue script here
}
&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
  /* Otp css here */
&amp;lt;/style&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moving to the template section of the component, we add the snippet below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div class="flex flex-row justify-between"&amp;gt;
   &amp;lt;input
      :style="style"
      v-model="inputs[idx]"
      :class="inputClass"
      @keyup="inputFocus"
      @focus="check($event)"
      @change="handleChange(idx, $event)"
      v-for="(inp, idx) in inputCount"
      :key="idx"
      :tabindex="idx"
      maxlength="1"
      autocomplete="off"
    /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For those who are familia with tailwind css, the &lt;code&gt;flex flex-row justify-between&lt;/code&gt; would be a familia concept but to those who are not familia with it, you need not to worry because these classes would be added to our &lt;code&gt;&amp;lt;style&amp;gt;&lt;/code&gt; section of the component manually.&lt;br&gt;
Normally, OTPs' are a group of inputs field which their collective values are regarded as one and takes on one input per input field, so we try to implement this feature by&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;using a &lt;code&gt;v-for&lt;/code&gt; to generate multiple input fields.&lt;/li&gt;
&lt;li&gt;setting &lt;code&gt;maxlength&lt;/code&gt; input attribute to &lt;code&gt;1&lt;/code&gt; to prevent more than one character per field&lt;/li&gt;
&lt;li&gt;setting &lt;code&gt;autocomplete&lt;/code&gt; input attribute to &lt;code&gt;off&lt;/code&gt; to prevent auto-completion which is not a feature of the OTP input&lt;/li&gt;
&lt;li&gt;creating event handlers like &lt;code&gt;@keyup&lt;/code&gt;, &lt;code&gt;@focus&lt;/code&gt;, &lt;code&gt;@change&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjp7wfcr8that21kx7u3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjp7wfcr8that21kx7u3.png" alt="Image description" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The we move to the script section of the component. As we had done before, we add the snippet below to the &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; section&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default {
  props: {
    inputCount: {
      type: Number,
      default: 4,
    },
    inputClass: String,
    dimension: {
      type: String,
      default: "30px",
    },
    value: [String, Number, Object],
  },
  data() { /* state properties */ }
  computed: { /* computed properties */ }
  watch: { /* watched properties */ }
  methods: { /* methods properties */ }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The props that this component would accept are &lt;code&gt;inputCount&lt;/code&gt; which refers to the number of OTP input fields, &lt;code&gt;inputClass&lt;/code&gt; which are extra styling for the fields, the &lt;code&gt;dimension&lt;/code&gt; i.e the size of each input field and the &lt;code&gt;value&lt;/code&gt; which is the literal value held by the OTP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default {
  ...
  computed: {
    style() {
      return `
        width: ${this.dimension}; 
        height: ${this.dimension}; 
        text-align: center;
      `;
    },
  },
  data() { /* state properties */ }
  watch: { /* watched properties */ }
  methods: { /* methods properties */ }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The computed property handles generating style for the dimensions, which is directly added to the input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default {
  ...
  data() {
    return {
      inputs: Array(this.inputCount),
      currentKey: 0,
    };
  },
  watch: { /* watched properties */ }
  methods: { /* methods properties */ }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the data property contains the state of this component. It holds and Array with length of the &lt;code&gt;inputCount&lt;/code&gt; added by via the props and the &lt;code&gt;currentKey&lt;/code&gt; which is the current position of the cursor on the fields.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default {
  ...
  watch: {
    value() {
      this.inputs = this.value.split("");
    },
  },
  methods: { /* methods properties */ }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We watch the &lt;code&gt;value&lt;/code&gt; props for any changes externally so the component can be updated too.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default {
  ...
  methods: {
    handleChange(key, event) {
      this.inputs[key] = event.target.value;
    },

    getChildren(event) {
      return event.target.parentElement.children;
    },

    check(event) {
      const inputs = this.getChildren(event);

      if (inputs[this.currentKey]){
        inputs[this.currentKey].focus();
      }
    },

    inputFocus(event) {
      const data = this.inputs.join("");
      const inputs = this.getChildren(event);

      this.$emit("input", data);
      if (data.length === this.inputCount) {
        this.$emit("completed", data);
      }

      if (event.key === "Delete" || event.key === "Backspace") {
        this.currentKey--;
        if (this.currentKey &amp;lt;= 0) {
          this.currentKey = 0;
        }
        if (inputs[this.currentKey]) {
          inputs[this.currentKey].focus();
        }
      } else {
        this.currentKey++;
        if (this.currentKey &amp;gt;= this.inputCount) {
          this.currentKey = this.inputCount;
        }
        if (inputs[this.currentKey]) {
          inputs[this.currentKey].focus();
        }
      }
    },
  },
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The methods used includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;handleChange&lt;/em&gt;: This is the handler for the &lt;code&gt;onchange&lt;/code&gt; event on the input component. On change, the value of the input field is stored in the &lt;code&gt;this.inputs&lt;/code&gt; state at the specified position &lt;code&gt;key&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;getChildren&lt;/em&gt;: This method gets the NodeList of input fields form the event parameter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;check&lt;/em&gt;: This is the &lt;code&gt;onfocus&lt;/code&gt; event handler. It calls the &lt;code&gt;.focus()&lt;/code&gt; method on the input field specified using the &lt;code&gt;this.currentKey&lt;/code&gt; content. Since the current key holds the current position of the cursor, it is easier to just use it the know which input to focus on.&lt;br&gt;
It also prevents focusing on non-existing input fields too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;inputFocus&lt;/em&gt;: This is the handler for the &lt;code&gt;onkeyup&lt;/code&gt; event. The OTP input are supposed to move to the next input field immediately after the character has been entered. So with this handler we make it happen.&lt;br&gt;
In this handler we emit the data of the total OTP input by joining them and using the &lt;code&gt;this.$emit("input", data);&lt;/code&gt; feature of vue components. &lt;br&gt;
Here we also handle the oncompleted feature of the OTP input i.e we emit back to the parent component that the inputs has been completely filled so that the next action can be carried out.&lt;br&gt;
We also handle the deleting of value from the field. This is the most delicate part of the OTP input since the delete feature requires the backwards movement of the cursor.&lt;br&gt;
As indicated in the snippet above, the &lt;code&gt;this.currentKey&lt;/code&gt; which hold the current position of the cursor on the input is reduced to handle for the backwards movement during delete.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the full OTP Input component code snippet&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class="flex flex-row justify-between"&amp;gt;
    &amp;lt;input
      :style="style"
      v-model="inputs[idx]"
      :class="inputClass"
      @keyup="inputFocus"
      @focus="check($event)"
      @change="handleChange(idx, $event)"
      v-for="(inp, idx) in inputCount"
      :key="idx"
      :tabindex="idx"
      maxlength="1"
      autocomplete="off"
    /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;script&amp;gt;
export default {
  props: {
    inputCount: {
      type: Number,
      default: 4,
    },
    inputClass: String,
    dimension: {
      type: String,
      default: "30px",
    },
    value: [String, Number, Object],
  },
  computed: {
    style() {
      return `
        width: ${this.dimension}; 
        height: ${this.dimension}; 
        text-align: center;
      `;
    },
  },
  data() {
    return {
      inputs: Array(this.inputCount),
      currentKey: 0,
    };
  },
  watch: {
    value() {
      this.inputs = this.value.split("");
    },
  },
  methods: {
    handleChange(key, event) {
      this.inputs[key] = event.target.value;
    },

    getChildren(event) {
      return event.target.parentElement.children;
    },

    check(event) {
      const inputs = this.getChildren(event);

      if (inputs[this.currentKey]){
        inputs[this.currentKey].focus();
      }
    },

    inputFocus(event) {
      const data = this.inputs.join("");
      const inputs = this.getChildren(event);

      this.$emit("input", data);
      if (data.length === this.inputCount) {
        this.$emit("completed", data);
      }

      if (event.key === "Delete" || event.key === "Backspace") {
        this.currentKey--;
        if (this.currentKey &amp;lt;= 0) {
          this.currentKey = 0;
        }
        if (inputs[this.currentKey]) {
          inputs[this.currentKey].focus();
        }
      } else {
        this.currentKey++;
        if (this.currentKey &amp;gt;= this.inputCount) {
          this.currentKey = this.inputCount;
        }
        if (inputs[this.currentKey]) {
          inputs[this.currentKey].focus();
        }
      }
    },
  },
}
&amp;lt;/script&amp;gt;
&amp;lt;style&amp;gt;
  /* Otp css here */
&amp;lt;/style&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After all that, We add the OTP Input component to our &lt;code&gt;App.vue&lt;/code&gt; file to test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxoz20cix540mewpn3g22.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxoz20cix540mewpn3g22.png" alt="Image description" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the final result&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhir4o1zqh6zw50o4gtyv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhir4o1zqh6zw50o4gtyv.png" alt="Image description" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7m5j2iu5nw67gqc5djvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7m5j2iu5nw67gqc5djvm.png" alt="Image description" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bugs&lt;/strong&gt;&lt;br&gt;
For most of it, it does what an otp input should do, but it still has some few bugs.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;After reaching the last input field, the delete feature works differently.&lt;/li&gt;
&lt;li&gt;if two keys are entered at the same time, it skips a field&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have any fix for these or you discover more bugs you can put it down in the comment section or raise an issue in the github repository&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Github:&lt;/strong&gt; &lt;a href="https://github.com/Otrex/vue-otp-input.git" rel="noopener noreferrer"&gt;https://github.com/Otrex/vue-otp-input.git&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
