<?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>Forem: haimantika mitra</title>
    <description>The latest articles on Forem by haimantika mitra (@haimantika).</description>
    <link>https://forem.com/haimantika</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%2F401142%2Fafaae4c7-9e8a-4d9c-9b9e-c9ef3d4b5a0d.jpg</url>
      <title>Forem: haimantika mitra</title>
      <link>https://forem.com/haimantika</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/haimantika"/>
    <language>en</language>
    <item>
      <title>How to Deploy Hermes' Self-Improving AI Agent</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Tue, 26 May 2026 16:00:00 +0000</pubDate>
      <link>https://forem.com/digitalocean/how-to-deploy-hermes-self-improving-ai-agent-4gm6</link>
      <guid>https://forem.com/digitalocean/how-to-deploy-hermes-self-improving-ai-agent-4gm6</guid>
      <description>&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;You host Hermes on a DigitalOcean Droplet (Ubuntu 24.04, at least 2 vCPUs and 4 GB RAM), install with the official script, and run &lt;code&gt;hermes setup&lt;/code&gt; for your LLM provider.&lt;/li&gt;
&lt;li&gt;The Telegram bot uses &lt;code&gt;hermes gateway setup&lt;/code&gt; and a persistent gateway service so Hermes stays reachable after you close SSH.&lt;/li&gt;
&lt;li&gt;Skills are Markdown files under &lt;code&gt;~/.hermes/skills/&lt;/code&gt;. MCP servers go in Hermes config and expose tools such as grocery search and cart actions.&lt;/li&gt;
&lt;li&gt;HTTP MCP with OAuth on a headless server uses the URL Hermes prints plus an SSH tunnel from your laptop browser to the Droplet loopback port.&lt;/li&gt;
&lt;li&gt;The grocery walkthrough uses Swiggy Instamart where available; you swap in another MCP URL for your region or stack.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;2026 is the year of agents doing the task for us rather than just guiding us to. We saw the rise of OpenClaw and now we have &lt;a href="https://hermes-agent.nousresearch.com/docs/" rel="noopener noreferrer"&gt;Hermes agent&lt;/a&gt;. It is an open-source, self-improving AI agent built by &lt;a href="https://nousresearch.com/" rel="noopener noreferrer"&gt;Nous Research&lt;/a&gt;. It has a built-in learning loop that creates skills from experience, improves them during use, nudges itself to persist knowledge, and builds a deepening model of who you are across sessions.&lt;/p&gt;

&lt;p&gt;In this tutorial, you will deploy Hermes on a &lt;a href="https://www.digitalocean.com/products/droplets" rel="noopener noreferrer"&gt;DigitalOcean Droplet&lt;/a&gt;, connect it to Telegram, and extend it with a custom skill. As a practical example, you will see how to build a grocery tracking agent that monitors daily consumption, alerts you when stock is low, and places orders automatically through a grocery delivery service.&lt;/p&gt;

&lt;p&gt;The grocery example uses &lt;a href="https://github.com/Swiggy/swiggy-mcp-server-manifest" rel="noopener noreferrer"&gt;Swiggy Instamart&lt;/a&gt;, which is available in India. But the approach works with any MCP-compatible service, such as a local grocery API, a task manager, a calendar, or a home automation system. The pattern is the same no matter what you connect.&lt;/p&gt;

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

&lt;p&gt;Before you begin, you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A DigitalOcean account. If you do not have one, &lt;a href="https://cloud.digitalocean.com/registrations/new" rel="noopener noreferrer"&gt;sign up here&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;A &lt;a href="https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu" rel="noopener noreferrer"&gt;DigitalOcean Droplet&lt;/a&gt; running Ubuntu 24.04 with at least 2 vCPUs and 4 GB RAM.
&lt;/li&gt;
&lt;li&gt;A Telegram account.
&lt;/li&gt;
&lt;li&gt;API key from an LLM provider. Hermes supports Anthropic, OpenAI, OpenRouter, and others.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What are we building
&lt;/h2&gt;

&lt;p&gt;Hermes is model-agnostic and platform-agnostic. It can connect to any tool that supports the &lt;a href="https://www.digitalocean.com/community/tutorials/control-apps-using-mcp-server" rel="noopener noreferrer"&gt;Model Context Protocol (MCP)&lt;/a&gt;, and it can send and receive messages on Telegram, WhatsApp, Discord, and Slack. You can find more information on their &lt;a href="https://hermes-agent.nousresearch.com/docs/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The architecture in this tutorial looks like this:&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%2Fv19jyonedh6059nid2fo.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%2Fv19jyonedh6059nid2fo.png" alt="Architecture" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s get started building:&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Create the Droplet
&lt;/h2&gt;

&lt;p&gt;Sign in to your DigitalOcean account and &lt;a href="https://cloud.digitalocean.com/droplets/new" rel="noopener noreferrer"&gt;create a new Droplet&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On the creation page, select:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Region:&lt;/strong&gt; The one closest to you
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image:&lt;/strong&gt; Ubuntu 24.04 LTS
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan:&lt;/strong&gt; Basic, with at least 2 vCPUs and 4 GB RAM (the &lt;code&gt;s-2vcpu-4gb&lt;/code&gt; size)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication:&lt;/strong&gt; SSH Key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you need help adding an SSH key, follow the &lt;a href="https://docs.digitalocean.com/products/droplets/how-to/add-ssh-keys/" rel="noopener noreferrer"&gt;DigitalOcean SSH key guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once the Droplet is created, SSH into it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@YOUR_DROPLET_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update the system before installing anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2. Install Hermes Agent
&lt;/h2&gt;

&lt;p&gt;Hermes provides an install script that handles all dependencies including Python, &lt;code&gt;uv&lt;/code&gt;, and the &lt;code&gt;hermes&lt;/code&gt; binary itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once it finishes, reload your shell so the &lt;code&gt;hermes&lt;/code&gt; command is available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the setup wizard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hermes setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The wizard will ask you to choose an LLM provider and enter your API key. Select your provider, paste your key, and Hermes will save it to &lt;code&gt;~/.hermes/.env&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Verify the installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hermes &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3. Connect Hermes to Telegram
&lt;/h2&gt;

&lt;p&gt;Hermes connects to Telegram through a bot. Run the gateway setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hermes gateway setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it asks which platform to use, select Telegram. Hermes will walk you through creating a bot with Telegram's BotFather. Follow the steps in your terminal.&lt;/p&gt;

&lt;p&gt;Once setup is complete, start the gateway:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hermes gateway start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To keep it running after you disconnect from the Droplet, enable it as a system service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;hermes-gateway
systemctl start hermes-gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open Telegram, find the bot you just created, and send it a message like "hello." If it responds, Hermes is connected and ready.&lt;/p&gt;

&lt;p&gt;You can now talk to Hermes from anywhere on your phone. Ask it to check the weather, set a reminder, search the web, or run a command on your Droplet. It handles all of this out of the box.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4. Understand skills and MCP servers
&lt;/h3&gt;

&lt;p&gt;Before building the automation example, let's understand two core Hermes concepts:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Skills&lt;/strong&gt; - These are Markdown files that teach Hermes how to handle specific tasks. You write a skill file describing what the task is, what triggers it, and what steps to follow. Hermes reads all skill files in &lt;code&gt;~/.hermes/skills/&lt;/code&gt; at startup and uses them to handle relevant requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP Servers&lt;/strong&gt; - It gives Hermes access to external services. &lt;a href="https://www.digitalocean.com/community/tutorials/model-context-protocol" rel="noopener noreferrer"&gt;MCP (Model Context Protocol)&lt;/a&gt; is an open standard that lets AI agents communicate with APIs in a structured way. If a service publishes an MCP server, Hermes can search its products, manage carts, read calendars, create tasks, and more. You add MCP servers to your Hermes config and Hermes uses them automatically when relevant.&lt;/p&gt;

&lt;p&gt;Together, skills and MCP servers let you build automations that are specific to your life and the tools you use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5. Build real-world automation: Grocery tracking
&lt;/h2&gt;

&lt;p&gt;Personally, I am very bad at keeping a tab of groceries and often find myself out of essential stock just when I am about to cook. So I wanted to automate this process for me. I eat similar food everyday and also measure my calories. I used all of this information to automate grocery shopping for me.&lt;/p&gt;

&lt;p&gt;The goal of Hermes was to track my daily grocery consumption, alert me on Telegram when something is running low, and place an order through a grocery delivery service when I say yes.&lt;/p&gt;

&lt;p&gt;This example uses the &lt;a href="https://github.com/Swiggy/swiggy-mcp-server-manifest" rel="noopener noreferrer"&gt;Swiggy Instamart MCP server&lt;/a&gt;, which is available in India. If you are in a different country, you can swap it out for any MCP-compatible grocery or delivery service. The skill logic stays exactly the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the skill file
&lt;/h3&gt;

&lt;p&gt;Create a directory for the skill:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.hermes/skills/grocery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create the skill file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano ~/.hermes/skills/grocery/grocery_tracker.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Paste the following and edit the &lt;code&gt;groceries:&lt;/code&gt; section to match your actual diet and quantities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Grocery Auto-Order Skill&lt;/span&gt;

&lt;span class="gu"&gt;### My Daily Grocery List&lt;/span&gt;

groceries:
&lt;span class="p"&gt;  -&lt;/span&gt; name: "Milk"
    unit: "ml"
    daily_consumption: 500
    reorder_quantity: 2000
    alert_threshold_days: 3
    search_query: "fresh milk 1 litre"
&lt;span class="p"&gt;
  -&lt;/span&gt; name: "Eggs"
    unit: "pieces"
    daily_consumption: 2
    reorder_quantity: 12
    alert_threshold_days: 3
    search_query: "eggs 12 pack"
&lt;span class="p"&gt;
  -&lt;/span&gt; name: "Oats"
    unit: "gm"
    daily_consumption: 60
    reorder_quantity: 1000
    alert_threshold_days: 7
    search_query: "rolled oats 1kg"

  # Add your own items following the same format

&lt;span class="gu"&gt;### Instructions for Hermes&lt;/span&gt;

&lt;span class="gu"&gt;#### Daily check&lt;/span&gt;
Read ~/.hermes/grocery_inventory.json. Subtract each item's
daily_consumption from its current quantity. For any item where
quantity / daily_consumption is less than or equal to
alert_threshold_days, send a Telegram alert listing the low
items and ask if the user wants to place an order.

&lt;span class="gu"&gt;#### On YES&lt;/span&gt;
Search each low item using its search_query at the user's saved
delivery address. Add reorder_quantity of each to cart. Send a
cart summary via Telegram with prices and total. Wait for CONFIRM.

&lt;span class="gu"&gt;#### On CONFIRM&lt;/span&gt;
Place the order. Update grocery_inventory.json with the restocked
quantities. Send a delivery confirmation message.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save with &lt;code&gt;Ctrl+O&lt;/code&gt;, then &lt;code&gt;Enter&lt;/code&gt;, then exit with &lt;code&gt;Ctrl+X&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the inventory file
&lt;/h3&gt;

&lt;p&gt;The inventory file tracks how much of each item you have at home right now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano ~/.hermes/grocery_inventory.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"last_updated"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-05-07"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"delivery_address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR FULL ADDRESS HERE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"snooze_until"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&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;"Milk"&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;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ml"&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;"Eggs"&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;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pieces"&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;"Oats"&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;"quantity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"unit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gm"&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;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;Replace the quantities with what you actually have at home. Save and exit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Connect to an MCP server
&lt;/h3&gt;

&lt;p&gt;Add the grocery service MCP to your Hermes config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hermes config edit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scroll to the bottom of the file and add your MCP server. For Swiggy Instamart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;mcp_servers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;swiggy-instamart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://mcp.swiggy.com/im"&lt;/span&gt;
    &lt;span class="na"&gt;auth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;oauth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For any other MCP-compatible service, replace the name and URL with the values from that service's documentation.&lt;/p&gt;

&lt;p&gt;Save and exit, then verify it appears:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hermes mcp list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6. Authenticate with your MCP server
&lt;/h2&gt;

&lt;p&gt;Most MCP servers require OAuth authentication. Because your Droplet is headless, the OAuth callback needs to reach your browser through an &lt;a href="https://www.digitalocean.com/community/tutorials/ssh-port-forwarding" rel="noopener noreferrer"&gt;SSH tunnel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Run the login command on your Droplet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hermes mcp login swiggy-instamart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hermes will print a URL containing a port number in the redirect URI, like &lt;code&gt;http://127.0.0.1:45123/callback&lt;/code&gt;. Note that port number.&lt;/p&gt;

&lt;p&gt;On your local machine, open a new terminal and run the SSH tunnel using that port:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/id_ed25519 &lt;span class="nt"&gt;-L&lt;/span&gt; 45123:127.0.0.1:45123 root@YOUR_DROPLET_IP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep that terminal open, then immediately open the URL from your Droplet in your browser and complete the login. You have about 30 seconds before the token expires, so have both terminals ready before you start.&lt;/p&gt;

&lt;p&gt;When authentication succeeds, your Droplet terminal will show:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Authenticated — tools available
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Telling Hermes Your Current Stock
&lt;/h3&gt;

&lt;p&gt;Start Hermes and initialize the inventory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hermes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Set up my grocery tracker. Ask me for current stock levels for each item in the grocery_tracker skill.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hermes will ask about each item one by one. Answer with what you currently have at home and it will update &lt;code&gt;grocery_inventory.json&lt;/code&gt; automatically. Once you have given the update, you will receive a message similar to this:&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%2Fio61346lvkbkrs9fvvvy.jpeg" 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%2Fio61346lvkbkrs9fvvvy.jpeg" alt="image2" width="708" height="1536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the daily alert
&lt;/h3&gt;

&lt;p&gt;Still inside Hermes, set up the cron job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add a daily cron at 8am: check my grocery inventory using the grocery_tracker skill, subtract daily consumption, and send me a Telegram message if anything is running low.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hermes will schedule this and confirm. From now on, every morning it checks your stock and messages you on Telegram if you need to reorder. This is how it 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhcclwz1w6o4zjddrvi1r.jpeg" 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%2Fhcclwz1w6o4zjddrvi1r.jpeg" alt="image3" width="800" height="1482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7. Test the full flow
&lt;/h2&gt;

&lt;p&gt;Send a test message to your Telegram bot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Check my groceries and tell me what's running low.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should receive a Telegram message like this:&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%2Flblvjle66s7ejl9uvviu.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%2Flblvjle66s7ejl9uvviu.png" alt="image4" width="800" height="1734"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reply &lt;strong&gt;YES&lt;/strong&gt;. Hermes searches your connected grocery service, builds a cart, and sends a summary.&lt;/p&gt;

&lt;p&gt;Once everything is set up, you can manage your agent entirely from Telegram:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Message&lt;/th&gt;
&lt;th&gt;What Hermes does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Check my groceries&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shows all items and days of stock remaining&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;I bought 12 eggs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Updates egg stock in the inventory file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Order groceries now&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Skips the check and goes straight to ordering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;What's running low?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lists items near their alert threshold&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SKIP&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Snoozes today's alert until tomorrow&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;You now have a self-hosted AI agent running on DigitalOcean that works for you around the clock. Hermes connects to Telegram and more messaging platforms so you can reach it from anywhere, and skills plus MCP servers let you extend it to handle almost anything.&lt;/p&gt;

&lt;p&gt;The grocery automation you built in this tutorial is a starting point. The pattern is reusable: write a skill file that describes the task, connect an MCP server that gives Hermes access to the right service, and set a cron job to trigger it automatically. The grocery automation is one example. The same pattern works for any repetitive task in your life. A few ideas to get you started:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bill reminders-&lt;/strong&gt; Create a skill that tracks recurring payments, calculates due dates, and alerts you three days before each bill is due.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Health tracking-&lt;/strong&gt;  Log your workouts or meals via Telegram and have Hermes summarize your week every Sunday.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Home automation-&lt;/strong&gt; Connect Hermes to a smart home MCP server and have it adjust lights, thermostats, or appliances based on a schedule or your location.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/nousresearch/hermes-agent" rel="noopener noreferrer"&gt;Hermes Agent on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.digitalocean.com/products/droplets/" rel="noopener noreferrer"&gt;DigitalOcean Droplets documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.digitalocean.com/products/droplets/how-to/add-ssh-keys/" rel="noopener noreferrer"&gt;How to add SSH keys to Droplets&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://core.telegram.org/bots/tutorial" rel="noopener noreferrer"&gt;Telegram BotFather guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hermes</category>
      <category>ai</category>
      <category>agents</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Automating onboarding emails with n8n and AutoSend</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Tue, 23 Dec 2025 04:15:43 +0000</pubDate>
      <link>https://forem.com/haimantika/automating-onboarding-emails-with-n8n-and-autosend-3480</link>
      <guid>https://forem.com/haimantika/automating-onboarding-emails-with-n8n-and-autosend-3480</guid>
      <description>&lt;p&gt;Building a SaaS? The first thing you will build in your SaaS platform is the onboarding process. In my &lt;a href="https://dev.to/haimantika/building-otp-based-authentication-system-with-clerk-and-autosend-13mm"&gt;last article, you learned&lt;/a&gt; how to build the authentication system, and in this article, you will learn how you can automate the welcome emails during sign-up.&lt;/p&gt;

&lt;p&gt;To build this, we will be using n8n and AutoSend, here’s a little about both the tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n8n: &lt;a href="https://n8n.io/" rel="noopener noreferrer"&gt;n8n&lt;/a&gt; is an automation tool that lets you connect apps and services without writing glue code everywhere. You build workflows visually, trigger something (like a webhook), run logic, call APIs, transform data, and ship results where you need them. It’s open-source, self-hostable, and flexible enough to power everything from simple automations to production-grade backend workflows.
&lt;/li&gt;
&lt;li&gt;AutoSend: &lt;a href="https://autosend.com/" rel="noopener noreferrer"&gt;AutoSend&lt;/a&gt; is a developer-first email API that makes sending transactional emails simple and reliable. You define templates once, trigger emails via an API or webhook, and AutoSend handles delivery, retries, and tracking. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s what we will be building today:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/vM6WrAxtCnE"&gt;
&lt;/iframe&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%2Fd3g9i2blm6s1ysnjlwg2.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%2Fd3g9i2blm6s1ysnjlwg2.png" alt="Email" width="800" height="461"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the workflow
&lt;/h2&gt;

&lt;p&gt;What happened above is, as soon as the user signed up with their details, a webhook was triggered which then made a Http call to the AutoSend API and sent the welcome email.&lt;br&gt;&lt;br&gt;
Here’s the entire workflow diagram:&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%2Fc68eas4qa6zysvxt7ejm.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%2Fc68eas4qa6zysvxt7ejm.png" alt="Mermaid diagram" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To explain the entire process step-by-step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;User fills signup form&lt;br&gt;&lt;br&gt;
Frontend collects and sends this to n8n Webhook via &lt;code&gt;POST&lt;/code&gt;:&lt;br&gt;&lt;br&gt;
&lt;code&gt;{&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;"name": "Haimantika",&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;"email": "test@gmail.com"&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;}&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Webhook receives the request&lt;br&gt;&lt;br&gt;
Data lands in:&lt;br&gt;&lt;br&gt;
&lt;code&gt;$json.body.name&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;$json.body.email&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;n8n makes an API call to AutoSend:&lt;br&gt;&lt;br&gt;
&lt;code&gt;POST https://api.autosend.com/v1/mails/send&lt;/code&gt;&lt;br&gt;&lt;br&gt;
And sends structured email payload:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
`{`  
 `"from": { "email": "no-reply@saascode.in", "name": "Team SaaSCode"`   
`},`  
    `"to":   { "email": "test@gmail.com", "name": "Haimantika" },`  
  `"subject": "Welcome to SaaSCode 🎉",`  
  `"html": "&amp;lt;h1&amp;gt;Hello Haimantika&amp;lt;/h1&amp;gt;"`  
    `}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Finally, AutoSend validates the request, renders the template and sends the email&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Building the n8n workflow
&lt;/h2&gt;

&lt;p&gt;The n8n workflow is simple, all that it includes is a webhook and a http request. &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%2Fipeo6vdjgodz0u9yb7p9.jpeg" 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%2Fipeo6vdjgodz0u9yb7p9.jpeg" alt="Workflow" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To build the workflow, here’s how you need to configure them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a webhook, change the HTTP method to &lt;code&gt;POST&lt;/code&gt;, give the path a unique name, e.g &lt;code&gt;user-signup&lt;/code&gt; and then keep the response timing to &lt;code&gt;Immediate&lt;/code&gt;. Copy the production URL and then keep it saved, we will add it to our application later.
&lt;/li&gt;
&lt;/ol&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%2Fclkuege1fpdkkqznmlb8.jpeg" 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%2Fclkuege1fpdkkqznmlb8.jpeg" alt="Webhook node" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Then you need to add a HTTP request, in that add the &lt;code&gt;https://api.autosend.com/v1/mails/send&lt;/code&gt; endpoint and keep the method as &lt;code&gt;POST&lt;/code&gt;.
a. Once this done, you need to add two headers:
i. Authorization: Bearer &amp;lt;API key&amp;gt;
ii. Content-type: application/json
b. Next, you will need to add a JSON body. Copy and paste the JSON below. Update the email and the message:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"from"&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;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test@saascode.in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Team SaaSCode"&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;"to"&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;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{$json.body.email}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{$json.body.name}}"&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;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Welcome to SaaSCode 🎉"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;h1&amp;gt;Hello {{$json.body.name}}&amp;lt;/h1&amp;gt;&amp;lt;p&amp;gt;Thanks for joining!&amp;lt;/p&amp;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;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello {{$json.body.name}}, Thanks for joining!"&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;&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%2Fup5navpjiuzkxbx5avr4.jpeg" 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%2Fup5navpjiuzkxbx5avr4.jpeg" alt="Http node" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The final step is to save and publish the workflow.
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Frontend integration
&lt;/h2&gt;

&lt;p&gt;The next step is to connect the frontend to the n8n workflow. For this particular demo, we are using a single &lt;code&gt;index.html&lt;/code&gt; file and you can find the &lt;a href="https://github.com/Haimantika/autosend-n8n-workflow" rel="noopener noreferrer"&gt;reference code here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The frontend uses the native fetch API to communicate with n8n. When the user submits the sign-up form, we prevent the default browser behavior and aggregate the input values into a JavaScript object:&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;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&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;trim&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="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&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;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we send a POST request to the n8n webhook endpoint.&lt;br&gt;&lt;br&gt;
&lt;em&gt;Note&lt;/em&gt;: &lt;em&gt;We include the &lt;code&gt;Content-Type: application/json\&lt;/code&gt; header so n8n can automatically parse the body.&lt;/em&gt;&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;response&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://hmitra.app.n8n.cloud/webhook-test/user-signup&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//the url we copied from n8n&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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;Content-Type&lt;/span&gt;&lt;span class="dl"&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;application/json&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;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&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;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;That’s really all there is to it.&lt;br&gt;&lt;br&gt;
With one webhook and one HTTP request in n8n, you’ve automated one of the most important parts of any SaaS: the first email a user receives after signing up. No background jobs, no custom mailer logic, no retry handling code scattered across your backend.&lt;/p&gt;

&lt;p&gt;What I like about this setup is the clear separation of responsibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The frontend just collects user input and sends it somewhere.
&lt;/li&gt;
&lt;li&gt;n8n acts as the glue and the control plane.
&lt;/li&gt;
&lt;li&gt;AutoSend sends emails.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once this is in place, you can keep extending it without touching your application code. Want to send a follow-up email after 24 hours? Add a Delay node. Want to route enterprise signups to a different template? Add a condition. Want to notify your internal team on Slack? Same workflow, one more node.&lt;br&gt;&lt;br&gt;
This is also why I prefer workflows for things like onboarding. These flows change often, especially early on. Keeping them outside your core codebase makes iteration much faster and much safer.&lt;br&gt;&lt;br&gt;
If you’re building a SaaS, this is one of those “set it up once and forget about it” pieces that pays off immediately.&lt;/p&gt;

&lt;p&gt;Here’s some resources if you would like to learn more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://community.n8n.io/c/getting-started-with-n8n/docs-and-tutorials/6" rel="noopener noreferrer"&gt;n8n documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.autosend.com/" rel="noopener noreferrer"&gt;AutoSend documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twilio.com/en-us/blog/insights/marketing-email-vs-transactional-email-whats-difference" rel="noopener noreferrer"&gt;Transactional vs marketing emails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hope you enjoyed reading this quick tutorial. Will see you next year with more such quick and fun content!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>automation</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building OTP based authentication system with Clerk and Autosend</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Wed, 26 Nov 2025 17:05:17 +0000</pubDate>
      <link>https://forem.com/haimantika/building-otp-based-authentication-system-with-clerk-and-autosend-13mm</link>
      <guid>https://forem.com/haimantika/building-otp-based-authentication-system-with-clerk-and-autosend-13mm</guid>
      <description>&lt;p&gt;Vibe-coding has got us thinking more about security. Earlier this year, we saw Leo’s SaaS under attack, it was experiencing bypassed subscriptions, abused API keys, and database corruption.&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%2F1y5xy6wihimabch27l2e.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%2F1y5xy6wihimabch27l2e.jpg" alt=" " width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Big tech giants are focusing a lot on building applications that are AI+security first. As developers, every solution that we build now needs security to be built into the design phase. The first step to any application (SaaS or not) is authentication, and companies like Clerk, Auth0, etc., have already made it easier for us to build authentication systems that are secure.&lt;/p&gt;

&lt;p&gt;While you can also use their pre-built solutions, you might also need to plug and play custom solutions, and this is exactly what we will learn in this blog: how we can use Clerk’s authentication system with Autosend to build a secure authentication system.&lt;/p&gt;

&lt;p&gt;To follow this article end-to-end, you will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Working knowledge of Next.js
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://clerk.com/" rel="noopener noreferrer"&gt;A Clerk account&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://autosend.com/" rel="noopener noreferrer"&gt;An Autosend account&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What is Autosend?
&lt;/h1&gt;

&lt;p&gt;I recently discovered &lt;a href="http://autosend.com" rel="noopener noreferrer"&gt;Autosend&lt;/a&gt; on X and thought about playing around with it over the weekend. By definition, Autosend is an email platform for developers and marketers to send and track transactional and marketing emails. If you have used other platforms like Resend and Twilio, it does compare with them. What stood out for me is the developer experience; the product is easy to use with a clear developer journey outlining the steps to follow to send a successful email, and the documentation is very easy to follow as well. Although it does not have a free account, the paid tier for someone like us starts from $1, where you can send up to 3000 emails, which is more than enough for people like us building hobby projects.&lt;/p&gt;

&lt;h1&gt;
  
  
  Integration flow
&lt;/h1&gt;

&lt;p&gt;To build this entire thing wouldn’t take you more than an hour. To make things easy, we are using Clerk’s &lt;a href="https://clerk.com/docs/nextjs/getting-started/quickstart" rel="noopener noreferrer"&gt;Next.js starter guide&lt;/a&gt; (you can also copy the prompt and get started faster in your AI IDE of choice/use the Cursor button) and then replace the email verification part with Autosend.&lt;/p&gt;

&lt;p&gt;In this implementation, Clerk manages user accounts and sessions, while Autosend handles email delivery for verification codes. Unlike Clerk's built-in email verification, we generate and validate our own codes, giving us complete control over the email content, delivery, and user experience.&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%2Fgsexoew7tnb9xtf46ikv.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%2Fgsexoew7tnb9xtf46ikv.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Step-by-Step Process: Building the Authentication Flow
&lt;/h1&gt;

&lt;p&gt;The authentication flow consists of six main stages: &lt;strong&gt;User Registration&lt;/strong&gt;, &lt;strong&gt;Code Generation&lt;/strong&gt;, &lt;strong&gt;Email Delivery&lt;/strong&gt;, &lt;strong&gt;Code Verification&lt;/strong&gt;, &lt;strong&gt;Validation&lt;/strong&gt;, and &lt;strong&gt;Session Creation&lt;/strong&gt;. Let's break down each step to understand how Clerk and Autosend work together to create a secure authentication experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: User initiates signup
&lt;/h2&gt;

&lt;p&gt;When a user visits the &lt;code&gt;/signup&lt;/code&gt; page and submits their credentials, the process begins.&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%2Fxb5ohop396d69pk2ex57.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%2Fxb5ohop396d69pk2ex57.png" alt=" " width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The signup page (&lt;code&gt;app/signup/page.tsx&lt;/code&gt;) presents a beautiful gradient-styled form where users enter their email and password. When they click "Sign Up", the &lt;code&gt;handleSubmit&lt;/code&gt; function is triggered:&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;handleSubmit&lt;/span&gt; &lt;span class="o"&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;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FormEvent&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Create the sign-up with Clerk&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;emailAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Send verification code via Autosend&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/send-verification&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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;Content-Type&lt;/span&gt;&lt;span class="dl"&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setPendingVerification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Show code input screen&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;h3&gt;
  
  
  What's happening under the hood
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Clerk's &lt;code&gt;signUp.create()&lt;/code&gt; creates a user account in their system
&lt;/li&gt;
&lt;li&gt;The account is created but &lt;strong&gt;not yet verified&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A POST request is sent to the &lt;code&gt;/api/send-verification&lt;/code&gt; endpoint
&lt;/li&gt;
&lt;li&gt;The UI switches to show the verification input screen&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Important configuration
&lt;/h3&gt;

&lt;p&gt;Disable Clerk’s built-in email verification:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Clerk Dashboard
&lt;/li&gt;
&lt;li&gt;User &amp;amp; Authentication → Email, Phone, Username
&lt;/li&gt;
&lt;li&gt;Turn OFF “Verify at sign-up”
&lt;/li&gt;
&lt;li&gt;Save changes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This allows verification to be handled by Autosend instead of Clerk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Backend generates verification code
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;/api/send-verification&lt;/code&gt; endpoint generates and stores a verification code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code generation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateCode&lt;/span&gt;&lt;span class="p"&gt;():&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;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;900000&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Storage with expiration
&lt;/h3&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;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateCode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;verificationCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;expiresAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 10 minutes&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Triggering email delivery
&lt;/h3&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;result&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;sendVerificationEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;code&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;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;verificationCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&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;NextResponse&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="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;result&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&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="nx"&gt;NextResponse&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="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Verification code sent via Autosend&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Autosend delivers the email
&lt;/h2&gt;

&lt;p&gt;The email is constructed and sent through Autosend’s API.&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%2Flhql95fyn2kt5ibjhhbe.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%2Flhql95fyn2kt5ibjhhbe.png" alt=" " width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Email construction
&lt;/h3&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendVerificationEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AutosendResponse&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;sendEmail&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Your verification code: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&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="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;htmlTemplate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;plainTextVersion&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;h3&gt;
  
  
  &lt;strong&gt;API call&lt;/strong&gt;
&lt;/h3&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;response&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.autosend.com/v1/mails/send&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTOSEND_API_KEY&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&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;application/json&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;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTOSEND_FROM_EMAIL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AUTOSEND_FROM_NAME&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authentication&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Your verification code: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&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="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&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="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&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;h2&gt;
  
  
  &lt;strong&gt;Step 4: User enters verification code&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The user enters the 6-digit code in the UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Verification screen&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;bg-blue-50 border border-blue-200 rounded-lg p-4&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;p&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;text-sm text-blue-800&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="err"&gt;📧&lt;/span&gt; &lt;span class="nx"&gt;We&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ve sent a verification code to &amp;lt;strong&amp;gt;{email}&amp;lt;/strong&amp;gt; via Autosend.
  &amp;lt;/p&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;input
  type="text"
  value={code}
  onChange={(e) =&amp;gt; setCode(e.target.value)}
  placeholder="Enter 6-digit code"
  maxLength={6}
  className="text-center text-2xl font-mono tracking-widest"
/&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Backend validates the code
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;/api/verify-code&lt;/code&gt; endpoint performs strict validation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Validation logic
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;async &lt;span class="k"&gt;function &lt;/span&gt;POST&lt;span class="o"&gt;(&lt;/span&gt;req: NextRequest&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  const &lt;span class="o"&gt;{&lt;/span&gt; email, code &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; await req.json&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  const stored &lt;span class="o"&gt;=&lt;/span&gt; verificationCodes.get&lt;span class="o"&gt;(&lt;/span&gt;email&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;stored&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;NextResponse.json&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;{&lt;/span&gt; success: &lt;span class="nb"&gt;false&lt;/span&gt;, error: &lt;span class="s2"&gt;"No verification code found. Please request a new one."&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
      &lt;span class="o"&gt;{&lt;/span&gt; status: 400 &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;stored.expiresAt &amp;lt; Date.now&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    verificationCodes.delete&lt;span class="o"&gt;(&lt;/span&gt;email&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;NextResponse.json&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;{&lt;/span&gt; success: &lt;span class="nb"&gt;false&lt;/span&gt;, error: &lt;span class="s2"&gt;"Verification code has expired. Please request a new one."&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
      &lt;span class="o"&gt;{&lt;/span&gt; status: 400 &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;stored.code &lt;span class="o"&gt;!==&lt;/span&gt; code&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;NextResponse.json&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;{&lt;/span&gt; success: &lt;span class="nb"&gt;false&lt;/span&gt;, error: &lt;span class="s2"&gt;"Invalid verification code. Please try again."&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
      &lt;span class="o"&gt;{&lt;/span&gt; status: 400 &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  verificationCodes.delete&lt;span class="o"&gt;(&lt;/span&gt;email&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;NextResponse.json&lt;span class="o"&gt;({&lt;/span&gt;
    success: &lt;span class="nb"&gt;true&lt;/span&gt;,
    message: &lt;span class="s2"&gt;"Email verified successfully"&lt;/span&gt;,
  &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Complete signup and create session
&lt;/h2&gt;

&lt;p&gt;After verification, Clerk finalizes signup and creates the user session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking status
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;console.log&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;SignUp status: &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;.status&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
console.log&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;Created session ID: &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;.createdSessionId&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Creating the session
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;complete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdSessionId&lt;/span&gt;&lt;span class="p"&gt;)&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;setActive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdSessionId&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;setIsRedirecting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;setLoading&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;setTimeout&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="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="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&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="mi"&gt;1000&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;And finally, users see a success screen and are then redirected to the homepage fully authenticated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complete flow visualization
&lt;/h2&gt;

&lt;p&gt;A visual diagram showing how Clerk, the API routes, Autosend, and the frontend connect together to build the entire authentication system.&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%2Fizka80nrw92awtuqr95p.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%2Fizka80nrw92awtuqr95p.png" alt=" " width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Ending Notes
&lt;/h1&gt;

&lt;p&gt;And that’s how you can easily build a fully functional and customizable authentication flow for your applications.&lt;/p&gt;

&lt;p&gt;A few things to keep in mind as you build on top of this: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security enhancements&lt;/strong&gt;: Consider adding rate limiting to prevent abuse, you don't want someone spamming your verification endpoint. Also, think about implementing attempt limits (maybe 3-5 tries) before requiring a new code.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User experience&lt;/strong&gt;: The 10-minute expiration works well, but you might want to add a "Resend code" button with a cooldown timer. Users appreciate this when emails take longer to arrive or they accidentally delete them. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern isn't limited to just signup flows either. You can use the same Clerk + Autosend combination for password resets, or magic link authentication. The beauty is that once you understand how these pieces fit together, you can adapt them to whatever authentication pattern your application needs.&lt;/p&gt;

&lt;p&gt;If you are interested to learn more about authentication,email platforms, and 2FA here are some helpful resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.microsoft.com/en-in/security/business/security-101/what-is-two-factor-authentication-2fa" rel="noopener noreferrer"&gt;What is two-factor authentication?&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://auth0.com/docs/get-started/identity-fundamentals/authentication-and-authorization" rel="noopener noreferrer"&gt;Authentication vs Authorization&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.autosend.com/" rel="noopener noreferrer"&gt;Autosend documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://clerk.com/docs" rel="noopener noreferrer"&gt;Clerk documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Mood Map - Draw all your feelings</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Sun, 19 Jan 2025 17:56:53 +0000</pubDate>
      <link>https://forem.com/haimantika/mood-map-draw-all-your-feelings-4eim</link>
      <guid>https://forem.com/haimantika/mood-map-draw-all-your-feelings-4eim</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github"&gt;GitHub Copilot Challenge &lt;/a&gt;: Transitions and Transformations&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;This year started with being diagnosed with PCOD, which means mood swings are a common part of my life. I go from feeling a ton of emotions in a day to nothing at all. Along with me, 60% of other women have it (yes, PCOD is that common).&lt;/p&gt;

&lt;p&gt;But mood swings are not just limited to people with a uterus. Every human being experiences certain moods and emotions daily. So I built the &lt;a href="https://mood-mapdraw.vercel.app/" rel="noopener noreferrer"&gt;Mood Map app&lt;/a&gt; to help turn these moods and feelings into masterpieces.&lt;/p&gt;

&lt;p&gt;Sneak peek of the app:&lt;br&gt;
&lt;iframe class="tweet-embed" id="tweet-1881038179018690665-252" src="https://platform.twitter.com/embed/Tweet.html?id=1881038179018690665"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1881038179018690665-252');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1881038179018690665&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the app
&lt;/h2&gt;

&lt;p&gt;I started building the app with listing 12 basic emotions that a human might feel, here’s a list of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Happiness&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sadness&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fear&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disgust&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Anger&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Excitement&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confusion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Envy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Empathetic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sympathy&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Triumph&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Satisfaction&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then, asked GitHub Copilot to list me one shape and colour that represents these moods. This is what it suggested:&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;Mood&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Shape&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Color&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Happiness&lt;/td&gt;
&lt;td&gt;Circle&lt;/td&gt;
&lt;td&gt;Bright Yellow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sadness&lt;/td&gt;
&lt;td&gt;Teardrop&lt;/td&gt;
&lt;td&gt;Deep Blue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fear&lt;/td&gt;
&lt;td&gt;Sharp Triangle&lt;/td&gt;
&lt;td&gt;Dark Purple&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disgust&lt;/td&gt;
&lt;td&gt;Irregular Blob&lt;/td&gt;
&lt;td&gt;Olive Green&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anger&lt;/td&gt;
&lt;td&gt;Jagged Spike&lt;/td&gt;
&lt;td&gt;Fiery Red&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Excitement&lt;/td&gt;
&lt;td&gt;Starburst&lt;/td&gt;
&lt;td&gt;Electric Blue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Confusion&lt;/td&gt;
&lt;td&gt;Spiral&lt;/td&gt;
&lt;td&gt;Pale Gray&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Envy&lt;/td&gt;
&lt;td&gt;Twisting Vine&lt;/td&gt;
&lt;td&gt;Deep Green&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Empathetic&lt;/td&gt;
&lt;td&gt;Interlocking Loop&lt;/td&gt;
&lt;td&gt;Warm Peach&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sympathy&lt;/td&gt;
&lt;td&gt;Gentle Wave&lt;/td&gt;
&lt;td&gt;Light Blue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Triumph&lt;/td&gt;
&lt;td&gt;Upward Arrow&lt;/td&gt;
&lt;td&gt;Gold&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Satisfaction&lt;/td&gt;
&lt;td&gt;Square&lt;/td&gt;
&lt;td&gt;Earthy Brown&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For the final step before coding, I went to &lt;a href="https://excalidraw.com/" rel="noopener noreferrer"&gt;Excalidraw&lt;/a&gt; to visualize how my app would look like, and then built this structure:&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%2Frw1kkzx6lcjrtshtntyt.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%2Frw1kkzx6lcjrtshtntyt.png" alt="Architecture diagram" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;You may not know how to use a paintbrush, but with technology, everyone can be an artist. So try out the app here 👉 &lt;a href="https://mood-mapdraw.vercel.app/" rel="noopener noreferrer"&gt;https://mood-mapdraw.vercel.app/&lt;/a&gt; , and when you do, feel free to share and tag me on X &lt;a href="https://x.com/HaimantikaM" rel="noopener noreferrer"&gt;@HaimantikaM&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Repo
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.dev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Haimantika" rel="noopener noreferrer"&gt;
        Haimantika
      &lt;/a&gt; / &lt;a href="https://github.com/Haimantika/Mood-map" rel="noopener noreferrer"&gt;
        Mood-map
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Mood Map Creator&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A web-based interactive tool for creating drawings, based on mood. This can help you relax and relieve stress.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Draw and manipulate shapes on a canvas&lt;/li&gt;
&lt;li&gt;Color selection for shapes&lt;/li&gt;
&lt;li&gt;Shape customization
&lt;ul&gt;
&lt;li&gt;Resize shapes using slider controls&lt;/li&gt;
&lt;li&gt;Rotate shapes with precise angle control&lt;/li&gt;
&lt;li&gt;Copy, cut, and paste shapes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Download created mood maps as PNG files&lt;/li&gt;
&lt;li&gt;Fully keyboard accessible&lt;/li&gt;
&lt;li&gt;Screen reader friendly&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Technologies&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Next.Js&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;li&gt;Lucide React (for icons)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Clone the repository&lt;/span&gt;
git clone https://github.com/{username}/Mood-map

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Install dependencies&lt;/span&gt;
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; mood-map
npm install

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Start development server&lt;/span&gt;
npm run dev&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Select a shape from the shape selector&lt;/li&gt;
&lt;li&gt;Choose a color from the color picker&lt;/li&gt;
&lt;li&gt;Click on the canvas to place the shape&lt;/li&gt;
&lt;li&gt;Modify shapes using:
&lt;ul&gt;
&lt;li&gt;Size slider (10-100)&lt;/li&gt;
&lt;li&gt;Rotation slider (0-360 degrees)&lt;/li&gt;
&lt;li&gt;Click on shapes to select them&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Keyboard Shortcuts&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Ctrl/Cmd + C&lt;/code&gt;: Copy selected shape&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl/Cmd + V&lt;/code&gt;: Paste copied shape&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl/Cmd&lt;/code&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Haimantika/Mood-map" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Copilot Experience
&lt;/h2&gt;

&lt;p&gt;This entire application was built with the help of Copilot, from ideation to fixing deployment errors.&lt;br&gt;
Here's how I used it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For generating color and shape for different moods, and the prompt was, &lt;code&gt;I am building a mood based drawing app, I have these moods: happiness, sadness, anger, etc, can you help me suggest a color and shape for each of them&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;For improving accessibility in the &lt;code&gt;page.tsx&lt;/code&gt; file, and the prompt for it was &lt;code&gt;Make this code more accessible&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%2Ftvo9zg0h0lyxg0m3ppte.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%2Ftvo9zg0h0lyxg0m3ppte.png" alt="Code updates" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To fix deployment errors, and the prompt was:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Got this error while deploying in Vercel:

Type error: Type '{}' is missing the following properties from type 'DrawingCanvasProps': selectedShape, selectedColor, shapes, setShapes, and 4 more.
  17 |           onShapeChange={setCurrentShape}
  18 |         /&amp;gt;
&amp;gt; 19 |         &amp;lt;Drawing /&amp;gt;
     |          ^
  20 |       &amp;lt;/div&amp;gt;
  21 |     &amp;lt;/div&amp;gt;
  22 |   )
Static worker exited with code: 1 and signal: null
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
Error: Command "yarn build" exited with 1` can you help me fix it?
- To generate the project README using the prompt, `Read the entire project and add a simply Readme for it that includes all about the project and what it does.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  GitHub Models
&lt;/h2&gt;

&lt;p&gt;I used two GitHub models for the entire project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GPT4 - To help in code generation and update&lt;/li&gt;
&lt;li&gt;Claude 3.5 - To write the README for the projects&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%2Fi39k5016uuvq44o6f8lo.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%2Fi39k5016uuvq44o6f8lo.png" alt="Generating README" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;I love building, and when I build for a cause, it is even better. I first discovered the painting concept in 2024, while casually strolling through the streets of Bangalore. Everything seemed to pause and feel peaceful for a moment when I picked up the sketch paints based on my mood and started coloring. &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%2Fdwk7fi1ms9dr1ik2hisv.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%2Fdwk7fi1ms9dr1ik2hisv.jpg" alt="Haimantika painting" width="800" height="1427"&gt;&lt;/a&gt;&lt;br&gt;
Now that I finally have an opportunity to build something, I want you all to feel that moment of peace with me. Embrace every feeling, every transition that you are going through with my &lt;a href="https://mood-mapdraw.vercel.app/" rel="noopener noreferrer"&gt;Mood Map&lt;/a&gt; app. The application is open-source, and I would love to have your ideas on what else I can add. As for my future plans, I want to make the app more scalable, add more features, and provide an option to generate the sketch while you just sit and paint.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>webdev</category>
      <category>ai</category>
    </item>
    <item>
      <title>How to become a Microsoft MVP</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Fri, 17 Jan 2025 14:58:46 +0000</pubDate>
      <link>https://forem.com/haimantika/how-to-become-a-microsoft-mvp-3jj4</link>
      <guid>https://forem.com/haimantika/how-to-become-a-microsoft-mvp-3jj4</guid>
      <description>&lt;p&gt;The year started with a good news, I received an email from Microsoft saying that I have been selected as an MVP in the web development category.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1874822880393076830-37" src="https://platform.twitter.com/embed/Tweet.html?id=1874822880393076830"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1874822880393076830-37');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1874822880393076830&amp;amp;theme=dark"
  }



 &lt;/p&gt;

&lt;p&gt;For those of you who aren’t aware of the term, &lt;a href="https://mvp.microsoft.com/en-us/mvp" rel="noopener noreferrer"&gt;Microsoft Most Valued Professionals&lt;/a&gt; is a program by Microsoft to recognize the efforts of technical community members who help in building, creating, advocating, and promoting their products. Unlike any other ambassador program, this program adds weight and can help you in your professional life ahead. Getting in is not easy, and you need to prove your merits/contribution to get selected and also continue contributing to stay an MVP.&lt;/p&gt;

&lt;p&gt;In this article, I will share how I became an MVP, and hoping it can help you prepare, if you are planning to become one.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I apply to become an MVP?
&lt;/h2&gt;

&lt;p&gt;You cannot apply to become an MVP. You have to be nominated by an existing MVP or a Microsoft employee to be able to apply to become one.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you are interested, you can also DM me with your work on&lt;/em&gt; &lt;a href="https://www.linkedin.com/in/haimantika-mitra/" rel="noopener noreferrer"&gt;&lt;em&gt;LinkedIn&lt;/em&gt;&lt;/a&gt; &lt;em&gt;or&lt;/em&gt; &lt;a href="https://x.com/HaimantikaM" rel="noopener noreferrer"&gt;&lt;em&gt;X(Twitter)&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  When does the application open?
&lt;/h3&gt;

&lt;p&gt;The MVP application stays open throughout the year. Whenever you are ready, ask your referrer to nominate you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does the process look like?
&lt;/h2&gt;

&lt;p&gt;Once you have been nominated, you will receive an email with links to a portal where you need to submit proof of the different kinds of contributions you have made to the Microsoft community. This could be blogs, videos, GitHub contributions, projects, or even social media posts. You can submit a maximum of 24 contributions under various categories. Along with that, you will need to answer a few questions about your interest in the program and how you plan to contribute in the future. You will have around 45 days to complete this, and you will get the decision within 90 days.&lt;/p&gt;

&lt;p&gt;For example, I was nominated on September 24th, 2024, had time until November 7th, 2024, to apply, and heard back from the team on January 1st, 2025.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do I get when I become a Microsoft MVP?
&lt;/h2&gt;

&lt;p&gt;There are a LOT of perks that you get as an MVP. Not sharing them all here (let’s save the best for when you get selected 😉)&lt;/p&gt;

&lt;p&gt;Here are some of the perks that I love:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Access to LinkedIn Premium for free for a year.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discount on Microsoft certification.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The MVP Award kit, the Credly badge, the recommendation letter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Early access to product releases, invite-only meetups, and Microsoft conferences like Build.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access to fellow MVPs, Microsoft advocates, and the wider community with an opportunity to build and network with everyone. &lt;em&gt;(I used to be a Microsoft Student Ambassador, and the network can be very helpful. You not only get friends but also people who can motivate you and help you professionally.)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tips to keep in mind while applying:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Try to contribute to the Microsoft ecosystem for at least a year. If you've been doing it for longer, that's even better. In my case, I worked extensively with Microsoft Power Platform in 2020 and continued through 2021. A few months later, I started working at Microsoft, then moved to different companies, built many projects with web technologies, and refocused on Microsoft technologies in late 2023. I applied for the MVP program in mid-2024.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Even though you can report a maximum of 24 contributions, try to have a few more and keep a list of what you did in a separate sheet for easy tracking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Keep your contributions paced out throughout the year. Do not try to do a lot of things in a month and then have no activity for months. This is a volunteering role, and what helps is being consistent throughout the year rather than jampacking everything in a month or two.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try to contribute in multiple areas. Writing blogs might be your forte, but also try to make a social media post out of it, or maybe use this content to help a few folks in the Microsoft forums. While this is not mandatory, it is a good practice and shows that you can contribute in multiple areas.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;And that’s a wrap for this article. If you have any followup questions, I am just a DM away &lt;a href="https://x.com/HaimantikaM" rel="noopener noreferrer"&gt;@HaimantikaM&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>microsoft</category>
      <category>community</category>
      <category>coding</category>
    </item>
    <item>
      <title>Interpreting Low-Code from the perspective of open-source SPL</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Thu, 09 Nov 2023 13:15:40 +0000</pubDate>
      <link>https://forem.com/haimantika/interpreting-low-code-from-the-perspective-of-open-source-spl-5o0</link>
      <guid>https://forem.com/haimantika/interpreting-low-code-from-the-perspective-of-open-source-spl-5o0</guid>
      <description>&lt;h1&gt;
  
  
  What kind of code is considered low？
&lt;/h1&gt;

&lt;p&gt;In recent years, the term "Low-Code" has gained popularity, giving rise to numerous entrepreneurial teams. Unlike the binary classification of long and short codes, Low-Code introduces the dimensions of high and low codes. Simply put, Low-Code aims to simplify coding, reducing the workload and lowering the expertise requirements for developers.&lt;/p&gt;

&lt;p&gt;In the Low-Code landscape, it's essential to assess the actual codebase. Many self-proclaimed low-code development platforms rely on frameworks and templates, offering simplicity for basic requirements. However, as complexity grows, these platforms often necessitate traditional coding languages like Java or C#.&lt;/p&gt;

&lt;p&gt;The essence of Low-Code lies in minimizing the amount of code, not just relying on templates. While templates address straightforward needs, many businesses require intricate coding solutions. The effectiveness of Low-Code is intricately tied to development efficiency.&lt;/p&gt;

&lt;p&gt;So, what qualifies as Low-Code? Primarily tailored for information system development (MIS), Low-Code is crucial for handling diverse and ever-changing requirements efficiently. In the realm of MIS, the core tasks revolve around Input, Process, and Output (IPO), with coding focusing on the 'Process' aspect, particularly efficient data processing.&lt;/p&gt;

&lt;p&gt;Structured data, prevalent in relational databases, is the primary focus for Low-Code. Java and C# struggle in this domain due to a lack of structured data objects and the inherent complexities of these languages. SQL, while accessible, faces challenges in ordered computation and procedural logic, leading to convoluted code and increased development costs.&lt;/p&gt;

&lt;p&gt;Python offers some relief with Pandas' dataframe, serving as a structured data object. However, Python's integration challenges and the dataframe's matrix-like nature limit its applicability. Scala provides a dataframe option but falls short in professionalism and imposes a learning curve, coupled with complex project environments.&lt;/p&gt;

&lt;p&gt;In conclusion, Low-Code thrives in simplifying code for structured data processing within information systems, offering efficiency benefits. Choosing the right Low-Code solution involves considering the language's proficiency in handling structured data and its overall suitability for complex business requirements.&lt;/p&gt;




&lt;h1&gt;
  
  
  SPL is the low code
&lt;/h1&gt;

&lt;p&gt;Is there not a kind of low enough code?&lt;/p&gt;

&lt;p&gt;Absolutely, there exists a form of code that meets the criteria of being low enough—enter SPL (Structured Process Language) from the open-source esProc.&lt;/p&gt;

&lt;p&gt;SPL emerged from Raqsoft's need for a robust solution in handling intricate operations within reporting tools. Traditional coding in SQL and Java proved challenging, leading Raqsoft to pioneer a new language tailored for these tasks—SPL.&lt;/p&gt;

&lt;p&gt;SPL boasts well-defined structured data objects, capable of efficiently managing both big and small datasets. While incorporating a modest amount of object-oriented syntax, SPL sidesteps esoteric concepts, focusing squarely on streamlined data processing. Resembling the simplicity of early BASIC language in program logic, SPL features fundamental constructs like branches, loops, and subprograms, ensuring ease of comprehension. Notably, SPL excels in supporting complex set and ordered operations, enhancing the simplicity of code composition.&lt;/p&gt;

&lt;p&gt;Let's move beyond words and delve into code. SPL code is structured in a grid, leveraging cells as variable names, a familiar concept for Excel users. Noteworthy characteristics include seamless support for stepwise operations, clear code hierarchy through grid indentation, and robust debugging functionalities. SPL stands as a testament to practical low-code solutions for intricate data operations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aEzJhYMK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpz22eorgaaewfl0fktv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aEzJhYMK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tpz22eorgaaewfl0fktv.png" alt="Image description" width="800" height="425"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In SPL, you can even use SQL directly (independent of database):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderDate&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2020-01-01'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;or&lt;/span&gt; 
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderDate&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2020-12-31'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="nb"&gt;year&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderDate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="k"&gt;count&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="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;  
&lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="nb"&gt;year&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;OrderDate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;  
&lt;span class="k"&gt;having&lt;/span&gt; &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;

&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrderId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dept&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;  
&lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Employees&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SellerId&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Eid&lt;/span&gt;

&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;Orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt; &lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;  
&lt;span class="k"&gt;left&lt;/span&gt; &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;ClientTable&lt;/span&gt; &lt;span class="n"&gt;ct&lt;/span&gt; &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SPL itself has the process control capability similar to Java, therefore, SPL can achieve the effect of Java + SQL whether there is database or not.&lt;/p&gt;

&lt;p&gt;Let’s compare it with other codes. For example, we want to calculate the maximum consecutive days that a stock keeps rising.&lt;br&gt;
Write it in SQL is like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;consecutive_days&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="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;consecutive_days&lt;/span&gt;
      &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="k"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;updown_flag&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;sdate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;no_up_days&lt;/span&gt;
            &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;sDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;LAG&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;over&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;order&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;sDate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                              &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="n"&gt;updown_flag&lt;/span&gt;
                  &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="k"&gt;share&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="k"&gt;group&lt;/span&gt; &lt;span class="k"&gt;by&lt;/span&gt; &lt;span class="n"&gt;no_up_days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is a bit difficult to understand, right? You can take it as an exercise and think about how it works.&lt;/p&gt;

&lt;p&gt;Coding in Python is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="n"&gt;aapl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_excel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;AAPL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;xlsx&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;continue_inc_days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;max_continue_inc_days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;aapl&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;shift&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;gt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;aapl&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;shift&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="n"&gt;continue_inc_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;continue_inc_days&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;max_continue_inc_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;continue_inc_days&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;max_continue_inc_days&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;lt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;continue_inc_days&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;max_continue_inc_days&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_continue_inc_days&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although this logic is not complicated, it is not very simple to code.&lt;/p&gt;

&lt;p&gt;As for Java, we won't try. You can imagine its complexity yourself.&lt;/p&gt;

&lt;p&gt;For the same operation, coding in SPL is as follows:&lt;br&gt;
| Header 1   | &lt;br&gt;
|------------|&lt;br&gt;
|1 =T("d:/AAPL.xlsx") |&lt;br&gt;
|2 =a=0,A1.max(a=if(price&amp;gt;price[-1],a+1,0)) |&lt;/p&gt;

&lt;p&gt;There is no loop statement in this code, because SPL has a large number of strong lambda syntax-style set functions. Many tasks that can only be achieved with loops in other languages can be done with a single statement in SPL.&lt;/p&gt;

&lt;p&gt;SPL solves the serious flaws of SQL, and combines the common advantages of Java and SQL. In addition, SPL can easily support the big data operation and multi-thread parallel computing, but for Python, it will find it at a loss when it encounters such situation. If you are interested in learning more SPL code examples, go to Raqforum.&lt;/p&gt;


&lt;h1&gt;
  
  
  More than a kind of low code
&lt;/h1&gt;

&lt;p&gt;SPL provides perfect data source support; it can support almost all data sources that you may or may not have heard of:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4nF10WkU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fdgy6ekc2zp1c0lea0sc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4nF10WkU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fdgy6ekc2zp1c0lea0sc.png" alt="Image description" width="454" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thus, it reduces a lot of work load of preparing the data interface and conversion.&lt;/p&gt;

&lt;p&gt;Since SPL is implemented in Java, it is provided with JDBC driver, and can be seamlessly embedded into Java applications:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="err"&gt;…&lt;/span&gt;
&lt;span class="nc"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;forName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"com.esproc.jdbc.InternalDriver"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Connection&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;DriverManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConnection&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jdbc:esproc:local://"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;Statement&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="o"&gt;.();&lt;/span&gt;
&lt;span class="nc"&gt;CallableStatement&lt;/span&gt; &lt;span class="n"&gt;st&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;prepareCall&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{call xxxx(?, ?)}"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="nc"&gt;ResultSet&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;st&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="err"&gt;…&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this way, SPL can be easily integrated into some application framework. Most developers only need to care about business logic and data structure, and don't even need to understand complex application architecture.&lt;/p&gt;

&lt;p&gt;In particular, for those “low code platforms” without code, they will have real low code after integrating the open-source SPL. Letting template and code to complement each other is a complete low-code platform.&lt;/p&gt;

&lt;p&gt;SPL is also the interpreted-execution dynamic language, and the scripts written can be placed outside the main application. In this way, not only does it reduce the coupling between the script and the main application, but it also brings the benefits of hot swap. After all, the business logic (especially query and report)is often changing. When the requirement changed, it can take effect immediately as long as the script is rewritten, and there is no need to restart the application. If Java code is used in this case, then... (it also shows that Java code is not low at all).&lt;/p&gt;

&lt;p&gt;To know more about SPL, check them out on &lt;a href="https://t.co/OZX5HXjqoz"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reference: &lt;a href="https://blog.scudata.com/interpreting-low-code-from-the-perspective-of-open-source-spl/"&gt;https://blog.scudata.com/interpreting-low-code-from-the-perspective-of-open-source-spl/&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Behind the pull request: tales from the open source world</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Mon, 30 Oct 2023 11:18:23 +0000</pubDate>
      <link>https://forem.com/appwrite/behind-the-pull-request-tales-from-the-open-source-world-19em</link>
      <guid>https://forem.com/appwrite/behind-the-pull-request-tales-from-the-open-source-world-19em</guid>
      <description>&lt;h3&gt;
  
  
  What is Hacktoberfest
&lt;/h3&gt;

&lt;p&gt;In the world of software development, October is more than just a month, it's a season of collaboration, innovation, and celebration. Welcome to Hacktoberfest – a global event that unites tech enthusiasts from every corner of the globe to celebrate open-source software.&lt;/p&gt;

&lt;p&gt;Hacktoberfest isn't just an event; it's a testament to the incredible impact that contributors can make in the open-source community. It's a time when the digital realm comes alive with the buzz of creativity and camaraderie, where individuals of all backgrounds and expertise levels come together to contribute their skills and passion to open-source projects.&lt;/p&gt;

&lt;p&gt;In this blog, we'll explore the significance of Hacktoberfest in the open-source community. We'll highlight how it guides newcomers and seasoned developers toward collaboration and shared knowledge. Additionally, we'll showcase inspiring success stories that exemplify the true spirit of open source.&lt;/p&gt;

&lt;p&gt;Now, let's dive into some real-life stories of contributors who have participated in Hacktoberfest and experienced the transformative power of open-source collaboration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspiring stories from the community
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A journey of discovery and connection&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first story is from &lt;a href="https://www.linkedin.com/in/sarthakroy2002/"&gt;Sarthak Roy&lt;/a&gt;, who says, “Well, I started using GitHub properly from February 2021. Hacktoberfest was the reason I found out Appwrite and many more orgs/tools/services in 2021 October. Then I started exploring various stuffs and learnt a ton. During Hacktoberfest 2022, I again contributed in multiple projects, including Appwrite. It all started with the hope of getting a swag in 2021, to enjoying open source and contributing. It also helped me connect with some amazing folks. ”&lt;/p&gt;

&lt;p&gt;Sarthak's story highlights the transformative power of Hacktoberfest, from initially participating for the swag to discovering the joy of open source and connecting with amazing people.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inspiring journey: From novice to maintainer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, let's hear from &lt;a href="https://www.linkedin.com/in/moumita-podder-663507217/"&gt;Moumita Roy&lt;/a&gt;, who had an amazing experience with Hacktoberfest. In her own words, "Well, first, I participated in Hacktoberfest 2022 after a friend encouraged me to register for it. Before that, I only knew that GitHub was for pushing code. But through Hacktoberfest, I learned about schemas and other terminologies. Since then, I have contributed to numerous open-source projects. I'm grateful to my friend for introducing me to the world of open source. As a student, I'm still learning and excited about Hacktoberfest 2023. This year, I plan to contribute and participate as a maintainer." Now, let's dive into Moumita's inspiring journey.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Embracing the open-source culture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The final story is from &lt;a href="https://www.linkedin.com/in/krishnendudg/"&gt;Krishnendu Dasgupta&lt;/a&gt; and he says, “One of the best things about Hacktoberfest for me is that it helped me become familiar with and accustomed to the open-source culture. I can still vividly remember Hacktoberfest 2018, when I was asking questions like "What is GitHub?" and learning about version control and collaboration through Git and GitHub. This experience was life-changing, as it continues to enable me to collaborate effectively with my teammates on any project.”&lt;/p&gt;

&lt;p&gt;Krishnendu added: “Another valuable lesson from events like Hacktoberfest is that open source is not just about making significant feature contributions or bringing about major changes. Every contribution matters, as long as it adds value to the main codebase.Last but not least, even if I didn't directly contribute to certain repositories, simply browsing through them made me realize the importance of maintaining good coding practices.”&lt;/p&gt;

&lt;p&gt;He further explained, “Overall, Hacktoberfest is definitely an event worth participating in. It was an eye-opener for me, highlighting the significance of collaboration and creating something great for others!”&lt;/p&gt;

&lt;p&gt;From the above stories, one thing is common: everyone needs to start from somewhere, and for them, that somewhere was Hacktoberfest! If you are someone who is looking to get started in open source, this is your chance!&lt;/p&gt;

&lt;h3&gt;
  
  
  Tips to start contributing
&lt;/h3&gt;

&lt;p&gt;Now that we've heard the inspiring stories of Hacktoberfest contributors, it's time to take the next step and embark on your own journey of contribution. If you're eager to make a meaningful impact in the open-source community, but unsure of where to begin, don't worry – we've got you covered. Starting your journey as a contributor can feel overwhelming, but fear not! &lt;/p&gt;

&lt;p&gt;These tips will help you make the most out of Hacktoberfest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Familiarize yourself with the official &lt;a href="https://hacktoberfest.com/"&gt;Hacktoberfest&lt;/a&gt; rules.&lt;/li&gt;
&lt;li&gt;Look for projects that align with your interests and skills.&lt;/li&gt;
&lt;li&gt;Choose 1-2 projects and join their communities.&lt;/li&gt;
&lt;li&gt;If you get stuck, don't hesitate to reach out to project maintainers or the community for help.&lt;/li&gt;
&lt;li&gt;Take the time to learn about the project and always read its contribution guidelines before you start.&lt;/li&gt;
&lt;li&gt;Begin with beginner-friendly or good-first issues.&lt;/li&gt;
&lt;li&gt;Provide clear descriptions and comments when documenting your pull requests.&lt;/li&gt;
&lt;li&gt;Lastly, remember to have fun and enjoy the process of contributing to open source. It's a rewarding experience that can lead to personal and professional growth.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here are a few projects that are participating in Hacktoberfest this year and you can contribute to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/search?q=owner%3Aappwrite+owner%3Autopia-php+owner%3Aopen-runtimes+label%3Ahacktoberfest+is%3Aopen+is%3Aissue&amp;amp;type=issues&amp;amp;state=open"&gt;Appwrite&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/illacloud/illa"&gt;ILLA Cloud&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/novuhq/novu/labels/Hacktoberfest"&gt;Novu&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find more participating repositories &lt;a href="https://github.com/search?q=hacktoberfest&amp;amp;type=repositories"&gt;here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>Data ownership and Backend-as-a-Service</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Tue, 17 Oct 2023 17:54:01 +0000</pubDate>
      <link>https://forem.com/haimantika/data-ownership-and-backend-as-a-service-1oi7</link>
      <guid>https://forem.com/haimantika/data-ownership-and-backend-as-a-service-1oi7</guid>
      <description>&lt;p&gt;A comment in our product hunt launch triggered an interesting discussion on data ownership when using BaaS (Backend-as-a-Service) platforms. &lt;/p&gt;

&lt;p&gt;We believe open sourced code bases and flexible choice of Cloud providers for database and storage can help, but that may also make the experience more complex and difficult for developers.&lt;/p&gt;

&lt;p&gt;What are trade offs you're willing to make to own more of your data, and what are trade offs you're willing to make for a more integrated and seemless expereince?&lt;/p&gt;

&lt;p&gt;Where would you benefit from more choices when building with a BaaS platform?&lt;/p&gt;

&lt;p&gt;Context: &lt;a href="https://www.producthunt.com/posts/appwrite-cloud-beta?comment=2848192"&gt;https://www.producthunt.com/posts/appwrite-cloud-beta?comment=2848192&lt;/a&gt;&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>webdev</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Building Apps with Bun and Appwrite</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Fri, 22 Sep 2023 11:26:08 +0000</pubDate>
      <link>https://forem.com/appwrite/building-apps-with-bun-and-appwrite-1k92</link>
      <guid>https://forem.com/appwrite/building-apps-with-bun-and-appwrite-1k92</guid>
      <description>&lt;p&gt;If you are a developer, your definition of &lt;code&gt;bun&lt;/code&gt; must have recently changed. From what we knew to be a round piece of bread, it is now a new runtime in JavaScript, and as Bun claims, it is faster than the rest! In this article, we will find out what Bun really is, how it compares with Node.js and Deno, and how you can build apps with Bun and Appwrite.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Bun?
&lt;/h3&gt;

&lt;p&gt;Bun is an all-in-one JavaScript runtime &amp;amp; toolkit designed for speed, complete with a bundler, &lt;a href="https://bun.sh/docs/cli/test"&gt;test runner&lt;/a&gt;, and Node.js-compatible &lt;a href="https://bun.sh/package-manager"&gt;package manager&lt;/a&gt;. &lt;br&gt;
To install Bun, follow the instructions here 👉 &lt;a href="https://bun.sh/"&gt;bun.sh&lt;/a&gt;&lt;br&gt;
It is built from scratch to serve the modern JavaScript ecosystem. It has three major design goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Speed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Elegant APIs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cohesive Developer Experience&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You may think, what is all the hype about? Building with JavaScript is now faster with Bun, which is production-ready with its latest version 1.0 release.&lt;/p&gt;

&lt;p&gt;Bun lets you read environment variables from a &lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt; file and utilize the familiar &lt;strong&gt;&lt;code&gt;fetch()&lt;/code&gt;&lt;/strong&gt; method, enabling you to access and handle data from external sources within your application.&lt;/p&gt;

&lt;p&gt;Bun also natively supports TypeScript out of the box. Other than that, it also supports &lt;code&gt;.js&lt;/code&gt;, &lt;code&gt;.cjs&lt;/code&gt;, &lt;code&gt;.mjs&lt;/code&gt;, &lt;code&gt;.jsx&lt;/code&gt;, and &lt;code&gt;.tsx&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Bonus: Bun package manager is known for its speed, offering faster package management as one of its key features. Even if you don't use Bun as a runtime, you can use Bun's built-in package manager, that can significantly speed up your development workflow.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Try it for yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun &lt;span class="nb"&gt;install
&lt;/span&gt;bun add &amp;lt;package&amp;gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nt"&gt;--dev&lt;/span&gt;|--production|--peer]
bun remove &amp;lt;package&amp;gt;
bun update &amp;lt;package&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The powers of Bun are endless. If you are interested to know more about the capabilities, read the &lt;a href="https://bun.sh/blog/bun-v1.0"&gt;release announcement&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How is Bun so fast?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Bun made some bold decisions to make this happen! It is not because they are using Zig or not using V8 nor because it's machine code. It is because of the mindset to make everything as highly performant as possible.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Other than that, there are things like: While installing a package, Bun doesn’t do a network check to see if it is downloading in the latest version. &lt;code&gt;@latest&lt;/code&gt; tags are effectively ignored in Bun. &lt;/p&gt;

&lt;p&gt;Also, making small adjustments, such as creating a list of labeled pointers instead of keeping the function pointers separately, greatly improved the speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction to Appwrite
&lt;/h3&gt;

&lt;p&gt;Explore the capabilities of Bun with &lt;a href="https://appwrite.io/"&gt;Appwrite&lt;/a&gt; - a backend platform to help you minimize time to create value. Appwrite abstracts away the complexities and repetitiveness of building a modern application so you can jump straight to the fun parts, building impactful features. &lt;/p&gt;

&lt;p&gt;We recently released version 1.4, which is packed with a lot of great features ranging from AI command center, one-click migration service, the next generation of Appwrite functions. You can read more about the 1.4 release in our &lt;a href="https://dev.to/appwrite/appwrite-14-brings-command-center-ai-one-click-migrations-and-upgraded-functions-1ch2#:~:text=We've%20just%20released%20Appwrite,even%20better%20security%20for%20users"&gt;announcement article&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Using Appwrite, you can quickly deploy and scale your Bun/JavaScript code base with ease. To achieve that, you can use Appwrite Functions.&lt;/p&gt;

&lt;p&gt;Appwrite Functions is available in multiple languages and runtimes (and Bun is one of them). This gives developers the ability to plug and play with Appwrite in the language of their choice. &lt;/p&gt;

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

&lt;p&gt;Appwrite functions are capable of doing more. In our latest release, we have added &lt;code&gt;Function templates&lt;/code&gt;, which means you’ll be able to add Functions engineered by the Appwrite team and community to your Appwrite project. Functions also have their own &lt;code&gt;domain&lt;/code&gt;, either custom or generated by Appwrite. This lets you write Appwrite Functions that act like typical REST endpoints to handle webhooks, custom integrations, or even serve HTML content. Appwrite Functions will now also fit into your existing workflow right alongside the rest of your code as you can deploy them directly from &lt;code&gt;Git&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Integrating Bun in Appwrite
&lt;/h3&gt;

&lt;p&gt;Now that you have been introduced to Bun and Appwrite, it is time to test them out! To use Bun in Appwrite, you need to use the latest version of Appwrite. &lt;/p&gt;

&lt;p&gt;Installing a self-hosted version of Appwrite is pretty straight-forward, all you need to do is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Have Docker installed&lt;/li&gt;
&lt;li&gt;Run the command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--volume&lt;/span&gt; /var/run/docker.sock:/var/run/docker.sock &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--volume&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;/appwrite:/usr/src/code/appwrite:rw &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--entrypoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"install"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    appwrite/appwrite:1.4.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For one-click setups, check out the &lt;a href="https://appwrite.io/docs/self-hosting"&gt;installation docs&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;To use Bun in Appwrite, you need to add it to &lt;code&gt;_APP_FUNCTIONS_RUNTIMES&lt;/code&gt; in the &lt;code&gt;.env&lt;/code&gt; file and restart your Appwrite instance with &lt;code&gt;docker compose up -d&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;Next, go ahead and create a Bun function using the &lt;a href="https://appwrite.io/docs/command-line"&gt;Appwrite CLI&lt;/a&gt; by running &lt;code&gt;appwrite init function&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Here’s a video showing you how to enable Bun and execute the function👇&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/U4DU0kriOhA"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Now that your function is set up, let us see some examples:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example 1:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Bun aims to provide a consistent and predictable module resolution system that just works. The specialty of Bun is that you can use &lt;code&gt;import&lt;/code&gt; or &lt;code&gt;require&lt;/code&gt; in the same file—they both work all the time.&lt;/p&gt;

&lt;p&gt;Use the following code in your function to test the above statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;lodash&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;lodash&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;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;underscore&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="k"&gt;async &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="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;numbers&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;5&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&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="na"&gt;withLodash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;lodash&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;without&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&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;withUnderscore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;without&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numbers&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="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 output will be:&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bun supports &lt;code&gt;.jsx&lt;/code&gt; and &lt;code&gt;.tsx&lt;/code&gt; files out of the box. Bun's internal transpiler converts JSX syntax into vanilla JavaScript before execution.&lt;/p&gt;

&lt;p&gt;Let us test with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;renderToString&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;react-dom/server&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="k"&gt;async &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="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;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello World!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Current time is &lt;span class="si"&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="nf"&gt;toLocaleTimeString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;renderToString&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="mi"&gt;200&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;Content-Type&lt;/span&gt;&lt;span class="dl"&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;text/html&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;&lt;em&gt;Note:  For the code to work, you need to run &lt;code&gt;bun install react react-dom&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When the function successfully executes, you will get the following output:&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Takeaways
&lt;/h3&gt;

&lt;p&gt;In this article, we learned about Bun and using it with Appwrite. While we support Node.js, Deno, and Bun within Appwrite, it is up to you to choose which one you want to build with. &lt;/p&gt;

&lt;p&gt;While comparing the performance of these three runtimes with Appwrite, we have come up with some interesting results:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build time - Bun is almost 3x faster than Node.js when installing un-cached dependencies for a Next.js project&lt;/li&gt;
&lt;li&gt;Cold-start - Bun is almost 2x faster than Node.js, and 3x faster than Deno&lt;/li&gt;
&lt;li&gt;Warm-start - All runtimes in similar ranges with differences ranging between 1-3ms&lt;/li&gt;
&lt;li&gt;Load testing - All in similar ranges, with Bun and Node.js being the most stable&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Benchmarks above are related to runtime used in Appwrite Functions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here are some resources to get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs/functions"&gt;Appwrite Function Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bun.sh/docs"&gt;Bun Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://discord.com/invite/appwrite"&gt;Appwrite Discord&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the benchmarks shared above and having the flexibility within Appwrite to build with any runtime, what would be your choice? 👀&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Add a Search Function to your application</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Mon, 18 Sep 2023 14:32:04 +0000</pubDate>
      <link>https://forem.com/appwrite/searching-simplified-with-meilisearch-and-appwrite-functions-287i</link>
      <guid>https://forem.com/appwrite/searching-simplified-with-meilisearch-and-appwrite-functions-287i</guid>
      <description>&lt;p&gt;As a part of Appwrite 1.4, one of the new features we have introduced to Appwrite Functions is Function Templates. Function templates are pre-built Appwrite Functions that can be integrated into your Appwrite project with just a few clicks. Using them, you can easily incorporate new features and integrations into your app without writing additional code or managing infrastructure.&lt;/p&gt;

&lt;p&gt;One such integration you can implement using Appwrite Functions is &lt;strong&gt;Searching&lt;/strong&gt; using &lt;strong&gt;Meilisearch&lt;/strong&gt;. In this blog we show how you can use an Appwrite Function Template to integrate search with Meilisearch.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up the Template
&lt;/h1&gt;

&lt;p&gt;Meilisearch is a flexible and powerful user-focused search engine that can be added to any website or application. The purpose of this function template is to sync documents in an Appwrite database collection to a Meilisearch index. Using this function template, users can explore, search, and retrieve information from the connected database collection. Through this template, documents from the Appwrite collection are systematically indexed within Meilisearch.&lt;/p&gt;

&lt;p&gt;To use the function, you need the following set of keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APPWRITE_KEY - API Key to talk to Appwrite backend APIs.To generate API Keys you can follow the documentation &lt;a href="https://appwrite.io/docs/getting-started-for-server#apiKey"&gt;here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;APPWRITE_ENDPOINT - To get the Appwrite endpoint, you need to go to &lt;a href="https://cloud.appwrite.io/"&gt;Appwrite&lt;/a&gt; and find it under “Settings”&lt;/li&gt;
&lt;li&gt;APPWRITE_DATABASE_ID - The ID of the Appwrite database that contains the collection to sync. You can find the documentation &lt;a href="https://appwrite.io/docs/databases"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;APPWRITE_COLLECTION_ID - The ID of the collection in the Appwrite database to sync.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To use Meilisearch, you can either self-host it using 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; curl &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;https://install.meilisearch.com]&lt;span class="o"&gt;(&lt;/span&gt;https://install.meilisearch.com/&lt;span class="o"&gt;)&lt;/span&gt; | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use &lt;a href="https://www.meilisearch.com/cloud"&gt;Meilisearch Cloud&lt;/a&gt;. For this example, we will assume that you are using Meilisearch Cloud. &lt;/p&gt;

&lt;p&gt;Here’s the keys you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MEILISEARCH_ENDPOINT - This is the host URL of the Meilisearch server. Once you have logged in to Meilisearch Cloud and created a new project, you will find the URL under “Overview” and this is how it should look like 👇&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73s2ed614ks90s6sgaot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73s2ed614ks90s6sgaot.png" alt="Overview Meilisearch" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; MEILISEARCH_ADMIN_API_KEY - This is the admin API key for Meilisearch. You will find it in the Meilisearch Console under “API Key”. &lt;/li&gt;
&lt;li&gt; MEILISEARCH_SEARCH_API_KEY - This is the API Key for Meilisearch search operations. To get this, you need you create a new index from the Meilisearch Console. Once created you will find it under &lt;code&gt;Overview&lt;/code&gt; as &lt;code&gt;Default Search API Key&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i30ebit62tcvglm7gn9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i30ebit62tcvglm7gn9.png" alt="Creating an index from the Console" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;MEILISEARCH_INDEX_NAME - Name of the Meilisearch index to which the documents will be synchronized. For e.g, in the above picture, the Index name is &lt;code&gt;Newindex&lt;/code&gt;. You can also find it under &lt;code&gt;Settings&lt;/code&gt; as &lt;code&gt;Index Name&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preparing the Function
&lt;/h2&gt;

&lt;p&gt;The function template syncs documents in an Appwrite database collection to a Meilisearch index. It should get you up and running, but you will need to add real data to build a useful search index.&lt;/p&gt;

&lt;p&gt;If you want to see the source code, you can find it on our &lt;a href="https://github.com/appwrite/templates/tree/main/node/sync-with-meilisearch"&gt;templates GitHub repository&lt;/a&gt;. Now, let’s navigate to our functions page on &lt;strong&gt;&lt;a href="https://cloud.appwrite.io/"&gt;Appwrite&lt;/a&gt;&lt;/strong&gt;. From there, we will select the &lt;strong&gt;Templates&lt;/strong&gt; tab, search for and select the &lt;strong&gt;Sync with Meilisearch&lt;/strong&gt; function template.&lt;/p&gt;

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

&lt;p&gt;The function requires &lt;code&gt;APPWRITE_API_KEY&lt;/code&gt;, &lt;code&gt;APPWRITE_DATABASE_ID&lt;/code&gt;, &lt;code&gt;APPWRITE_COLLECTION_ID&lt;/code&gt; , &lt;code&gt;MEILISEARCH_ENDPOINT&lt;/code&gt;, &lt;code&gt;MEILISEARCH_ADMIN_API_KEY&lt;/code&gt;, &lt;code&gt;MEILISEARCH_SEARCH_API_KEY&lt;/code&gt;, &lt;code&gt;MEILISEARCH_INDEX_NAME&lt;/code&gt;. Once you have added them you can proceed to the Connect step.&lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Create a new repository&lt;/strong&gt; (this will generate a GitHub repository for you with the function), and leave the production branch and root settings as default to create this function.&lt;/p&gt;

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

&lt;h1&gt;
  
  
  Testing the Template
&lt;/h1&gt;

&lt;p&gt;Visit the &lt;strong&gt;Domains&lt;/strong&gt; tab on the function page and copy the domain URL to test the function.&lt;/p&gt;

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

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;We’ve added search functionality to our app and opened up many possibilities to improve the experience of our app’s users.&lt;/p&gt;

&lt;p&gt;How can the &lt;em&gt;template&lt;/em&gt; be extended ?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using events to automatically index new collections&lt;/li&gt;
&lt;li&gt;Using weights and other meilisearch features to optimise search such as excluding certain fields from indexing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some examples are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Real-time Data Exploration:&lt;/strong&gt; It can be used to provide real-time search capabilities for datasets and data streams, allowing users to explore and analyze data in real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content Management Systems:&lt;/strong&gt; The function template can be integrated into content management systems (CMS) to facilitate efficient content retrieval for editors and site visitors. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Be sure to check out the other available Function Templates. We’ve created multiple that could be of use in your projects. You can find the &lt;a href="https://github.com/appwrite/templates"&gt;templates GitHub repository here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more information about Appwrite and Appwrite Functions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://appwrite.io/docs/functions"&gt;Appwrite Function Docs&lt;/a&gt;&lt;/strong&gt;: These documents provide more information on how to use Appwrite Functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://dev.to/appwrite/serverless-your-way-unleashing-appwrite-functions-true-potential-2l4f"&gt;Functions Announcement&lt;/a&gt;&lt;/strong&gt;: Read the full announcement on Functions 1.4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://discord.com/invite/appwrite"&gt;Appwrite Discord&lt;/a&gt;&lt;/strong&gt;: Connect with other developers and the Appwrite team for discussion, questions, and collaboration.&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Add a URL Shortener Function to Your Application</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Wed, 13 Sep 2023 08:52:49 +0000</pubDate>
      <link>https://forem.com/appwrite/add-a-url-shortener-to-your-application-with-functions-19hl</link>
      <guid>https://forem.com/appwrite/add-a-url-shortener-to-your-application-with-functions-19hl</guid>
      <description>&lt;p&gt;As a part of Appwrite 1.4, one of the new features we have introduced to Appwrite Functions is Function Templates. Function templates are pre-built Appwrite Functions that can be integrated into your Appwrite project with just a few clicks. Using them, you can easily incorporate new features and integrations into your app without writing additional code or managing infrastructure.&lt;/p&gt;

&lt;p&gt;A URL shortener takes a long or complex URL and generates a shorter, more concise version. The primary purpose of a URL shortener function is to make links easier to share, manage, and remember.&lt;br&gt;
For e.g &lt;a href="https://dev.to/appwrite/introducing-appwrite-migrations-effortless-data-migration-from-your-platforms-5dhh"&gt;https://dev.to/appwrite/introducing-appwrite-migrations-effortless-data-migration-from-your-platforms-5dhh&lt;/a&gt; to &lt;a href="http://tinyurl.com/bd5usb3n"&gt;http://tinyurl.com/bd5usb3n&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;In this blog, we’ll learn to build a URL shortener using Appwrite Functions template. The template benefits from the built-in scalability, reliability, and security of Appwrite Functions.&lt;/p&gt;

&lt;p&gt;You can find the source code on our &lt;a href="https://github.com/appwrite/templates/tree/main/node/url-shortener"&gt;templates GitHub repository&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;To get started, you need to navigate to the functions page on the &lt;strong&gt;&lt;a href="https://appwrite.io/cloud"&gt;Appwrite&lt;/a&gt;&lt;/strong&gt; console. From there, we will select the &lt;strong&gt;Templates&lt;/strong&gt; tab, search for and select the &lt;strong&gt;URL Shortener&lt;/strong&gt; function template.&lt;/p&gt;

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

&lt;p&gt;The function requires two variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APPWRITE_API_KEY&lt;/li&gt;
&lt;li&gt;SHORT_BASE_URL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftthf0alfwhce03zr6c8b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftthf0alfwhce03zr6c8b.png" alt="Appwrite console - adding variables" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have populated those, you can go straight to the &lt;strong&gt;Connect&lt;/strong&gt; step.&lt;/p&gt;

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

&lt;p&gt;Select &lt;strong&gt;Create a new repository&lt;/strong&gt; (this will generate a GitHub repository for you with the function), and leave the production branch and root settings as default to create this function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Function
&lt;/h2&gt;

&lt;p&gt;Visit the &lt;strong&gt;Domains&lt;/strong&gt; tab on the function page and copy the domain URL to test the function.&lt;/p&gt;

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

&lt;p&gt;Go to the function URL in your web browser, and you'll see a short url like the one shown below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;URL shorteners often offer additional features such as tracking click-through rates, providing analytics on link usage, and allowing users to customize the shortened URL to some extent.This Function Template can be extended to perform a lot of functionalities. Some examples are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Link Analytics and Tracking:&lt;/strong&gt; Enhance the URL shortener to track click-through rates, geographical location of users, referral sources, and other analytics data. This could provide valuable insights into the popularity and effectiveness of shared links.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Link Management Dashboard:&lt;/strong&gt; Create a user-friendly dashboard where users can manage their shortened links, view statistics, and perform various actions on their links.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Be sure to check out the other available Function Templates. We’ve created many that could be of use in your projects. You can find the &lt;a href="https://github.com/appwrite/templates"&gt;templates GitHub repository here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For more information about Appwrite and Appwrite Functions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://appwrite.io/docs/functions"&gt;Appwrite Function Docs&lt;/a&gt;&lt;/strong&gt;: These documents provide more information on how to use Appwrite Functions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://dev.to/appwrite/serverless-your-way-unleashing-appwrite-functions-true-potential-2l4f"&gt;Functions Announcement&lt;/a&gt;&lt;/strong&gt;: Read the full announcement on Functions 1.4.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://discord.com/invite/appwrite"&gt;Appwrite Discord&lt;/a&gt;&lt;/strong&gt;: Connect with other developers and the Appwrite team for discussion, questions, and collaboration.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>tutorial</category>
      <category>functions</category>
      <category>git</category>
    </item>
    <item>
      <title>Introducing 1.4 Lightning Hackathon: Functions</title>
      <dc:creator>haimantika mitra</dc:creator>
      <pubDate>Mon, 11 Sep 2023 11:38:01 +0000</pubDate>
      <link>https://forem.com/appwrite/lightning-hackathon-functions-3fhf</link>
      <guid>https://forem.com/appwrite/lightning-hackathon-functions-3fhf</guid>
      <description>&lt;p&gt;&lt;a href="https://dev.to/appwrite/serverless-your-way-unleashing-appwrite-functions-true-potential-2l4f"&gt;Appwrite Functions&lt;/a&gt; has just had a fresh upgrade, and we are so excited we are hosting a lightning-round hackathon focusing on functions. It will last 10 days only - but no worries! With our newly released functions, you can add functionality to your application with just a few clicks!&lt;/p&gt;

&lt;h3&gt;
  
  
  How to join
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;No registration is required. Just start coding using function templates!&lt;/li&gt;
&lt;li&gt;Join the Appwrite Discord community in channel #lightninghackathon&lt;/li&gt;
&lt;li&gt;Please choose the MIT license on your GitHub repo.&lt;/li&gt;
&lt;li&gt;Submit your GitHub repo and the requested information here: &lt;a href="https://apwr.dev/LightningHackathon"&gt;https://apwr.dev/LightningHackathon&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Submit your project to &lt;a href="https://builtwith.appwrite.io"&gt;https://builtwith.appwrite.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Share your creation on social media using #LightningHackathon and by tagging @appwrite&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Key dates
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Start date: Sept 21st, 2023, 11:00AM CST&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;End date: Oct 1st, 2023, 11:00AM CST &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Rules &amp;amp; Criteria
&lt;/h3&gt;

&lt;p&gt;So, what are the rules for joining the hackathon?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build whatever you like using Appwrite functions.&lt;/li&gt;
&lt;li&gt;You can be part of a team or join individually, but do note there is only one prize per winning team or individual.&lt;/li&gt;
&lt;li&gt;You or your team can submit as many projects as you like, so long as you use Appwrite functions.&lt;/li&gt;
&lt;li&gt;You can use any language or framework.&lt;/li&gt;
&lt;li&gt;Please choose the MIT license on your GitHub repo.&lt;/li&gt;
&lt;li&gt;Submit your repo using this form and share your repo online while tagging Appwrite and using #LightningHackathon.&lt;/li&gt;
&lt;li&gt;Only one person per team has to submit the &lt;a href="https://apwr.dev/LightningHackathon"&gt;Typeform&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;You are allowed to add as many submissions as you want to increase your chances of winning.&lt;/li&gt;
&lt;li&gt;Some criteria our judges will look out for are creativity, usage of functions, technical components, visually pleasing&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prizes
&lt;/h3&gt;

&lt;p&gt;The prizes are a customized Appwriter or an Appwrite t-shirt. Each winning entry will receive one of the prizes. In case you enter as a team, only one prize will be shipped.&lt;/p&gt;

&lt;p&gt;We will have a total of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 winners, each winning one Appwriter keyboard&lt;/li&gt;
&lt;li&gt;10 runner-ups, each winning one Appwrite t-shirt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: We only give out one prize per team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Community help
&lt;/h3&gt;

&lt;p&gt;You can find the Appwrite team and the rest of the community on Discord. We will be here to help you build, find project partners, or just come and hang out and learn! &lt;/p&gt;

&lt;p&gt;In order to get support, you will need to join our #lightning-hackathon Discord channel. &lt;a href="https://appwrite.io/discord"&gt;Join us on Discord.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;For you to get you started, we collected some useful resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://appwrite.io/docs/functions"&gt;Appwrite Functions Docs&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/appwrite/serverless-your-way-unleashing-appwrite-functions-true-potential-2l4f"&gt;Functions introduced&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/appwrite/deploy-a-pdf-generation-service-in-minutes-with-appwrite-functions-4p5f"&gt;PDF Function Template&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/appwrite/deploy-a-pdf-generation-service-in-minutes-with-appwrite-functions-4p5f"&gt;ChatGPT Function Template&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/appwrite/send-whatsapp-messages-with-vonage-and-appwrite-functions-14hp"&gt;WhatsApp x Vonage Function Template&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/appwrite/templates"&gt;Functions Templates GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://appwrite.io/docs/client/functions"&gt;Function Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hackathon</category>
      <category>opensource</category>
      <category>git</category>
    </item>
  </channel>
</rss>
