<?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: Ashita</title>
    <description>The latest articles on Forem by Ashita (@itsashita).</description>
    <link>https://forem.com/itsashita</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%2F3426743%2Fd1d34146-03a5-4caa-840f-5a1e353ddbfc.jpg</url>
      <title>Forem: Ashita</title>
      <link>https://forem.com/itsashita</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/itsashita"/>
    <language>en</language>
    <item>
      <title>Agent Watch:Stop Telling Your AI Agent the Same Thing Twice! ✋</title>
      <dc:creator>Ashita</dc:creator>
      <pubDate>Sun, 15 Feb 2026 21:15:45 +0000</pubDate>
      <link>https://forem.com/itsashita/agent-watchstop-telling-your-ai-agent-the-same-thing-twice-1cpc</link>
      <guid>https://forem.com/itsashita/agent-watchstop-telling-your-ai-agent-the-same-thing-twice-1cpc</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a group submission for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;"Auto-sync your AI instructions with every commit using agent-watch"&lt;/em&gt;, a git hook that reads your commits and conversations, then uses AI to keep all your agent instruction files current — so your AI tools always know what your codebase looks like today. &lt;/p&gt;

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

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/p3pT7oQQsNE"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

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

&lt;p&gt;AI coding assistants like Claude Code, GitHub Copilot, Cursor, Windsurf and Cline, each read an instruction file(&lt;code&gt;CLAUDE.md&lt;/code&gt;, &lt;code&gt;.cursorrules&lt;/code&gt;, &lt;code&gt;copilot-instructions.md&lt;/code&gt;, etc.) to understand your project's conventions, architecture, and rules.&lt;br&gt;
But here's the thing: &lt;em&gt;&lt;strong&gt;Your codebase changes every day&lt;/strong&gt;&lt;/em&gt;. &lt;em&gt;&lt;strong&gt;Those instruction files don't&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You could refactor a module, swap a library or change an API pattern, yet your AI agent is still giving advice based on stale instructions. You are  either manually updating those files (&lt;strong&gt;tedious&lt;/strong&gt;) or you don't (&lt;strong&gt;getting worse AI suggestions over time&lt;/strong&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  What Agent Watch Does
&lt;/h3&gt;

&lt;p&gt;It plugs into your git workflow and &lt;strong&gt;automatically updates your AI instruction files after every commit or push&lt;/strong&gt;. No manual effort.&lt;/p&gt;

&lt;p&gt;Here's the flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jl95wx9xje8gmbv97oo.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%2F4jl95wx9xje8gmbv97oo.png" alt="architectural-workflow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Git hook fires&lt;/strong&gt; - on commit or push, &lt;code&gt;agent-watch run&lt;/code&gt; is triggered automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart filter checks&lt;/strong&gt; - skips entirely if only docs, configs, or lock files changed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sessions extracted&lt;/strong&gt; - pulls latest 3 unprocessed sessions from Claude Code, Copilot Chat, and Copilot CLI.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Patterns summarized&lt;/strong&gt; - Copilot CLI distills each session into actionable conventions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Atomic update&lt;/strong&gt; - a single &lt;code&gt;copilot --yolo&lt;/code&gt; command updates all agent files at once with combined context&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it. Your AI tools always have fresh, accurate instructions.&lt;/p&gt;
&lt;h3&gt;
  
  
  What This Means for You as a Developer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Your AI assistants get smarter over time — they learn as your codebase evolves, not just when you remember to update a config file&lt;/li&gt;
&lt;li&gt;Zero maintenance overhead — you never touch those instruction files manually again.&lt;/li&gt;
&lt;li&gt;Works with whatever AI tool you use — one tool keeps Claude, Copilot, Cursor, Windsurf, and Cline all in sync.&lt;/li&gt;
&lt;li&gt;Doesn't slow you down — smart filtering skips running when you only change docs, lock files, or configs.&lt;/li&gt;
&lt;li&gt;Fits your existing workflow — supports Lefthook, Husky, or plain git hooks. Just &lt;code&gt;agent-watch init&lt;/code&gt; and forget about it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  The Bigger Picture
&lt;/h3&gt;

&lt;p&gt;AI coding assistants are only as good as the context they have. Agent Watch closes the gap between &lt;strong&gt;what your codebase actually looks like&lt;/strong&gt; and &lt;strong&gt;what your AI tools think it looks like&lt;/strong&gt;. It turns static instruction files into living documents that evolve with your code.&lt;/p&gt;

&lt;p&gt;It's a small tool that solves a real, growing pain point — and as AI-assisted development becomes the norm, keeping agent context fresh isn't optional anymore. It's table stakes.&lt;/p&gt;
&lt;h2&gt;
  
  
  How GitHub Copilot CLI is leveraged for this tool
&lt;/h2&gt;

&lt;p&gt;Agent Watch doesn't contain any AI logic itself. It's purely plumbing — git hooks, file detection, context gathering, and state tracking. &lt;strong&gt;All the intelligence is delegated to GitHub Copilot CLI.&lt;/strong&gt; Every time Agent Watch needs to summarize sessions, understand code patterns, or update agent files, it shells out to Copilot CLI with a carefully crafted prompt. The final update uses a single &lt;code&gt;copilot --yolo&lt;/code&gt; command that reads and updates all agent files atomically in one pass. Copilot CLI is the brain; Agent Watch is the nervous system that triggers it at the right time with the right context.&lt;/p&gt;
&lt;h3&gt;
  
  
  3 Distinct Uses of Copilot CLI
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1) Creating Missing Agent Files&lt;/strong&gt;&lt;br&gt;
During &lt;code&gt;agent-watch init&lt;/code&gt;, if a selected agent file doesn't exist, Copilot CLI analyzes your codebase and generates a tailored starting file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) Updating Agent Files on Every Commit&lt;/strong&gt;&lt;br&gt;
The core use. On each git hook trigger, Agent Watch gathers context (commit message, changed files, diff stats, chat sessions) and asks Copilot CLI to intelligently merge new patterns into each managed agent file — or skip if nothing meaningful changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3) Extracting Chat Session History&lt;/strong&gt;&lt;br&gt;
Agent Watch discovers your past Copilot conversations, filters to the current project, and asks Copilot CLI to summarize them. These insights feed into the agent file updates above.&lt;/p&gt;
&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1.Installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global installation(Highly Recommended)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g agent-watch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;As a dev dependency&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D agent-watch


 # or


pnpm add -D agent-watch

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

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Run directly without installation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx agent-watch init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;2. Initialize your project&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd your-project
agent-watch init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Before vs. After using agent-watch
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Before agent-watch:-
&lt;/h3&gt;

&lt;p&gt;You're building a Node.js backend. Over the course of a sprint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monday:&lt;/strong&gt; You set up Express with a centralized error handler middleware.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tuesday:&lt;/strong&gt; You adopt Drizzle ORM and write all queries through a repository pattern&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wednesday:&lt;/strong&gt; You add JWT auth with refresh tokens and role-based access&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Thursday:&lt;/strong&gt; A teammate asks Cursor to write a new endpoint — it uses raw SQL, &lt;code&gt;try/catch&lt;/code&gt; in every route, and rolls its own auth check&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⛔&lt;strong&gt;PROBLEM&lt;/strong&gt;⛔: Your AI agent files are stuck in the past. Every assistant on the team is guessing instead of following what you've already established. &lt;/p&gt;
&lt;h3&gt;
  
  
  After agent-watch:-
&lt;/h3&gt;

&lt;p&gt;Every commit automatically updates your agent instruction files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monday commit:&lt;/strong&gt; "Use centralized error handler — never catch errors in individual routes"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tuesday commit:&lt;/strong&gt; "Use Drizzle ORM with repository pattern — no raw SQL"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wednesday commit:&lt;/strong&gt; "Auth uses JWT with refresh tokens — use &lt;code&gt;requireRole()&lt;/code&gt; middleware"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Thursday commit:&lt;/strong&gt; Teammate's Cursor already knows all of this. It generates the endpoint correctly on the first try.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;RESULT:&lt;/strong&gt; Conventions are captured as they emerge, not weeks later when someone remembers to update a config file. Every AI assistant on your team stays aligned — automatically. ✅&lt;/p&gt;
&lt;h2&gt;
  
  
  Challenges Faced(and how Copilot CLI helped)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Git hooks without breaking existing setups&lt;/strong&gt;&lt;br&gt;
Teams use Lefthook, Husky, or raw hooks. &lt;strong&gt;Copilot CLI&lt;/strong&gt; helped us design marker-based injection that works alongside any existing setup and is safe to re-run.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Discovering chat sessions across three AI tools&lt;/strong&gt;&lt;br&gt;
Claude Code, Copilot Chat, and Copilot CLI all store sessions in different locations and formats. We use Copilot CLI to summarize sessions from all three into a unified format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Combining everything into one coherent update&lt;/strong&gt;&lt;br&gt;
Sessions could easily produce noisy, duplicate updates.&lt;code&gt;copilot --yolo&lt;/code&gt; command takes all summaries and file paths, then updates every agent file automically in one pass.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Takeaway:&lt;/strong&gt; Agent Watch is plumbing. Every intelligent decision is a Copilot CLI call at the right moment with the right context.&lt;/p&gt;
&lt;h2&gt;
  
  
  Repository
&lt;/h2&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/surnr" rel="noopener noreferrer"&gt;
        surnr
      &lt;/a&gt; / &lt;a href="https://github.com/surnr/agent-watch" rel="noopener noreferrer"&gt;
        agent-watch
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      CLI tool that uses git hooks to keep your AI agent configuration files in sync with your codebase
    &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;Agent Watch&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Keep your AI agents in sync with your evolving codebase—automatically.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agent Watch is a CLI tool that captures knowledge from your development workflow—git commits, code changes, and AI chat sessions—and intelligently updates your AI agent configuration files. Stop manually copying patterns from chat sessions. Stop forgetting to update CLAUDE.md or Copilot instructions. Let agent-watch learn from your work and keep your AI agents informed.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why Agent Watch?&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;The Problem&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;You're having productive conversations with Claude Code, GitHub Copilot, and other AI assistants. They help you establish patterns, conventions, and best practices. But this knowledge stays trapped in chat history. Your agent configuration files (CLAUDE.md, copilot-instructions.md, etc.) become outdated within days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Your AI assistants keep making the same mistakes. They forget your team's conventions. You waste time repeating yourself.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;The Solution&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Agent Watch automatically:&lt;/p&gt;


&lt;ul&gt;

&lt;li&gt;✅ &lt;strong&gt;Extracts patterns&lt;/strong&gt; from your Claude Code, Copilot Chat, and Copilot CLI sessions&lt;/li&gt;

&lt;li&gt;✅…&lt;/li&gt;

&lt;/ul&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/surnr/agent-watch" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  Package
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/agent-watch" rel="noopener noreferrer"&gt;agent-watch&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributors
&lt;/h2&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/itsashita"&gt;@itsashita&lt;/a&gt; x &lt;a class="mentioned-user" href="https://dev.to/surnr"&gt;@surnr&lt;/a&gt; &lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>From Spaghetti Code to Orchestrated Workflows: Building AyurAI with Motia &amp; Mux</title>
      <dc:creator>Ashita</dc:creator>
      <pubDate>Mon, 05 Jan 2026 07:49:59 +0000</pubDate>
      <link>https://forem.com/itsashita/from-spaghetti-code-to-orchestrated-workflows-building-ayurai-with-motia-mux-4eoo</link>
      <guid>https://forem.com/itsashita/from-spaghetti-code-to-orchestrated-workflows-building-ayurai-with-motia-mux-4eoo</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/mux-2025-12-03"&gt;DEV's Worldwide Show and Tell Challenge Presented by Mux&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;AyurAI&lt;/strong&gt; is a comprehensive AI-powered Ayurvedic wellness platform that democratizes access to holistic healthcare. The platform seamlessly integrates three core pillars:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. AI Voice Assistant
&lt;/h3&gt;

&lt;p&gt;Users can engage in natural, conversational exchanges with an intelligent wellness advisor powered by VAPI. Available 24/7, the assistant provides personalized Ayurvedic guidance without the barrier of cost or availability. It's trained to provide authentic Ayurvedic advice while being accessible to modern users.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Practitioner Appointment System
&lt;/h3&gt;

&lt;p&gt;A complete booking and management system that connects users with certified Ayurvedic doctors. Users can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;View available practitioners and their schedules&lt;/li&gt;
&lt;li&gt;Book appointments with conflict detection&lt;/li&gt;
&lt;li&gt;Receive confirmation emails automatically&lt;/li&gt;
&lt;li&gt;Track their consultation history&lt;/li&gt;
&lt;li&gt;Manage upcoming appointments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system handles complex scenarios like preventing double-bookings, checking doctor availability, and automatically notifying both patient and practitioner.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Educational Video Library
&lt;/h3&gt;

&lt;p&gt;A curated collection of Ayurvedic wellness videos with professional streaming capabilities. Users can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browse wellness content&lt;/li&gt;
&lt;li&gt;Stream videos with adaptive quality&lt;/li&gt;
&lt;li&gt;Resume from where they left off&lt;/li&gt;
&lt;li&gt;Autogenerated thumbnail by Mux&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't just video hosting—it's a complete learning journey with progress tracking and a personalized experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User Dashboard&lt;/strong&gt; - Wellness journey overview, completed visits tracking, upcoming appointments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Admin Dashboard&lt;/strong&gt; - Doctor management, video uploads, appointment analytics, performance metrics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dark Mode UI&lt;/strong&gt; - Optimized for comfortable viewing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/devandop/ayur-ai" rel="noopener noreferrer"&gt;https://github.com/devandop/ayur-ai&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ayurai/
├── src/
│   ├── app/                    # Next.js App Router
│   │   ├── dashboard/          # User dashboard + video library
│   │   ├── admin/              # Admin dashboard
│   │   ├── appointments/       # Booking system
│   │   └── voice/              # AI assistant
│   ├── components/
│   │   ├── ui/                 # Radix + shadcn components
│   │   ├── dashboard/          # Dashboard components
│   │   └── admin/              # Admin components
│   ├── hooks/                  # React Query hooks
│   └── lib/actions/            # Server actions
│
├── backend/
│   ├── src/api/                # Motia workflow steps
│   │   ├── create-appointment.step.ts
│   │   ├── admin-add-video.step.ts
│   │   └── ...
│   └── src/events/             # Event handlers
│
└── prisma/schema.prisma        # Database schema
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Running Locally
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Frontend&lt;/span&gt;
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev

&lt;span class="c"&gt;# Backend (separate terminal)&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;backend
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Required environment variables: &lt;code&gt;DATABASE_URL&lt;/code&gt;, &lt;code&gt;CLERK_SECRET_KEY&lt;/code&gt;, &lt;code&gt;MUX_TOKEN_ID&lt;/code&gt;, &lt;code&gt;MUX_TOKEN_SECRET&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Story Behind It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Inspiration
&lt;/h3&gt;

&lt;p&gt;Ayurveda has guided millions toward wellness for over 5,000 years. It's a sophisticated medical system that views health holistically—not as the absence of disease, but as a state of balance in body, mind, and consciousness.&lt;/p&gt;

&lt;p&gt;Yet here we are in 2025, and accessing Ayurvedic wisdom remains surprisingly difficult:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Pain Points:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scarcity&lt;/strong&gt; - Qualified Ayurvedic practitioners are rare and concentrated in certain regions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt; - Consultations are expensive, often unaffordable for the average person&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inconvenience&lt;/strong&gt; - Scheduling requires travel, time off work, and planning&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fragmentation&lt;/strong&gt; - Knowledge is scattered across books, blogs, and individual practitioners&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Impermanence&lt;/strong&gt; - Guidance comes and goes—there's no continuous journey tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted to solve this. Not by replacing traditional Ayurveda, but by making it accessible.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Realization
&lt;/h3&gt;

&lt;p&gt;I noticed that successful health platforms share a pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Instant Access&lt;/strong&gt; - Users get help immediately (not days later)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Professional Backup&lt;/strong&gt; - AI is great, but human expertise matters&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Education&lt;/strong&gt; - Users learn and take ownership of their health&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Continuity&lt;/strong&gt; - Progress is tracked and visible over time&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;AyurAI combines all four.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Highlights
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Challenge: Building a Robust Backend
&lt;/h3&gt;

&lt;p&gt;Traditional backend architecture would require:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Routes → Controllers → Services → Database
↓
Manual event handling
↓
Complex error recovery
↓
Tightly coupled code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Solution: Event-Driven Workflows with Motia
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Isolated Workflow Steps
↓
Declarative Event Emission
↓
Automatic Event Orchestration
↓
Self-Documenting Code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Motia Was The Right Choice
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Declarative, Self-Documenting Workflows&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Instead of buried business logic, each workflow is clear and explicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApiRouteConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api&lt;/span&gt;&lt;span class="dl"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CreateAppointment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/appointments&lt;/span&gt;&lt;span class="dl"&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="s1"&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;emits&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="s1"&gt;appointment.created&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;        &lt;span class="c1"&gt;// ← Clear what this produces&lt;/span&gt;
  &lt;span class="na"&gt;flows&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="s1"&gt;appointment-management&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;      &lt;span class="c1"&gt;// ← Declares the flow it belongs to&lt;/span&gt;
  &lt;span class="na"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;errorHandlerMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="c1"&gt;// ← Built-in error handling&lt;/span&gt;
    &lt;span class="nx"&gt;clerkAuthMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                 &lt;span class="c1"&gt;// ← Authentication&lt;/span&gt;
    &lt;span class="nx"&gt;RateLimiters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;moderate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;               &lt;span class="c1"&gt;// ← Rate limiting&lt;/span&gt;
    &lt;span class="nx"&gt;SanitizationPresets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;medicalNotes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;// ← Input sanitization&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;Anyone reading this knows exactly what the step does, what security is applied, and what events it produces.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Event-Driven Orchestration&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;When an appointment is created, instead of manually writing callback chains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// With Motia - it's just one line:&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;appointment.created&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;appointmentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;patientEmail&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&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;doctorName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doctor&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;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;appointment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;time&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;Motia automatically triggers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Email notifications (via separate event handler)&lt;/li&gt;
&lt;li&gt;Analytics tracking (via separate event handler)&lt;/li&gt;
&lt;li&gt;Notification caching (via separate event handler)&lt;/li&gt;
&lt;li&gt;Any future handlers we add (no code changes needed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Zero manual coordination.&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Built-in Middleware Stack&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Motia provides production-grade middleware out of the box:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication Middleware:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clerkAuthMiddleware&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApiMiddleware&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;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&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;clerkUserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x-clerk-user-id&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;clerkId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;clerkUserId&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;update&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;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;create&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;clerkId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;clerkUserId&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;firstName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lastName&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="p"&gt;;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;next&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;strong&gt;Rate Limiting:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rateLimiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRateLimiter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;maxRequests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;windowSeconds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;keyExtractor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ctx&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anonymous&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;p&gt;&lt;strong&gt;Input Sanitization:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sanitizeString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&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;str&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;sanitized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;removeControlCharacters&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;sanitized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;trimAndLimit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sanitized&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;maxLength&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="nx"&gt;sanitized&lt;/span&gt; &lt;span class="o"&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;stripHTML&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;stripHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sanitized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;sanitizeHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sanitized&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;sanitized&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are applied consistently across all workflows.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;Type-Safe Event Handling&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Events are typed and validated using Zod:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;responseSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&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="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CONFIRMED&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="s1"&gt;COMPLETED&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="s1"&gt;CANCELLED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="na"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;nullable&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="c1"&gt;// ... more fields&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;responseSchema&lt;/span&gt;&lt;span class="p"&gt;:&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="nx"&gt;responseSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&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;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&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="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&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;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a response doesn't match the schema, it fails loudly. This catches bugs before they hit production.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. &lt;strong&gt;Scalability Through Event Queuing&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Using BullMQ under the hood, events are queued and processed reliably:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Event Emission
    ↓
BullMQ Queue
    ↓
Event Processors
    ↓
Database Updates / Emails / Analytics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If an event handler fails, it automatically retries with exponential backoff.&lt;/p&gt;

&lt;h4&gt;
  
  
  6. &lt;strong&gt;Visual Debugging with Motia Workbench&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The Motia Workbench provides a visual interface showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All workflow steps and their connections&lt;/li&gt;
&lt;li&gt;Real-time event flows&lt;/li&gt;
&lt;li&gt;Failed workflows with stack traces&lt;/li&gt;
&lt;li&gt;Performance metrics&lt;/li&gt;
&lt;li&gt;Request/response logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of blindly searching through logs, you can see exactly what happened.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-World Example: Appointment Booking Flow
&lt;/h3&gt;

&lt;p&gt;Here's how AyurAI handles a complete appointment booking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. User submits appointment form
   ↓
2. POST /api/appointments hits CreateAppointment step
   ↓
3. Validation layer (Zod schema)
   ↓
4. Auth middleware (verify user)
   ↓
5. Rate limiting (max 30 bookings/minute)
   ↓
6. Sanitization (clean user input)
   ↓
7. Database checks:
   - Doctor exists and is active?
   - Time slot available?
   - User doesn't have conflict?
   ↓
8. Create appointment record
   ↓
9. Emit 'appointment.created' event
   ↓
10. Motia automatically triggers:
    ├─ Email to user (confirmation)
    ├─ Email to doctor (new appointment)
    ├─ Analytics tracking (appointment created)
    └─ Cache invalidation (user appointments cache)
   ↓
11. Return success to frontend
    ↓
12. Frontend optimistically updates UI
    ↓
13. TanStack Query refetches and syncs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Not a single line of manual coordination code.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Comparison: Motia vs Traditional Express
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Express&lt;/th&gt;
&lt;th&gt;Motia&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Boilerplate&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual routes, controllers, services&lt;/td&gt;
&lt;td&gt;Declarative steps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Events&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual pub/sub setup&lt;/td&gt;
&lt;td&gt;Built-in, automatic orchestration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Middleware&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Write custom, apply manually&lt;/td&gt;
&lt;td&gt;Built-in, composable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Write catch/finally blocks&lt;/td&gt;
&lt;td&gt;Automatic retry logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scaling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manage queues manually&lt;/td&gt;
&lt;td&gt;BullMQ integrated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Separate OpenAPI specs&lt;/td&gt;
&lt;td&gt;Self-documenting config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Testing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Spy on internals&lt;/td&gt;
&lt;td&gt;Test steps independently&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Debugging&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Log diving&lt;/td&gt;
&lt;td&gt;Visual workflow tracing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Use of Mux (Additional Prize Category Participants Only)
&lt;/h3&gt;

&lt;p&gt;Most platforms use Mux only for video hosting. AyurAI goes much deeper.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Direct Upload Infrastructure
&lt;/h3&gt;

&lt;p&gt;Instead of uploading videos to my server (which is slow and storage-intensive), admins upload &lt;strong&gt;directly to Mux&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Step 1: Create upload URL&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uploads&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;new_asset_settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;playback_policy&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="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Returns: { id, url }&lt;/span&gt;
&lt;span class="c1"&gt;// Admin uploads to this URL directly&lt;/span&gt;
&lt;span class="c1"&gt;// Video never touches my servers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server bandwidth savings&lt;/li&gt;
&lt;li&gt;Faster uploads&lt;/li&gt;
&lt;li&gt;No storage costs&lt;/li&gt;
&lt;li&gt;Secure direct transfer&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Automatic Asset Processing
&lt;/h3&gt;

&lt;p&gt;Once uploaded, Mux automatically:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encoding:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Converts to VP9, H.264, H.265&lt;/li&gt;
&lt;li&gt;Multiple quality levels (720p, 1080p, 4K)&lt;/li&gt;
&lt;li&gt;Generates HLS and DASH streams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Thumbnail Generation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extracts key frames&lt;/li&gt;
&lt;li&gt;Generates optimized thumbnails&lt;/li&gt;
&lt;li&gt;Available at: &lt;code&gt;https://image.mux.com/{playbackId}/thumbnail.jpg&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AyurAI automatically stores this URL&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;video&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;muxAssetId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;muxPlaybackId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playback_ids&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;thumbnailUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://image.mux.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playback_ids&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/thumbnail.jpg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&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;
  
  
  3. Adaptive Bitrate Streaming
&lt;/h3&gt;

&lt;p&gt;Mux serves the appropriate quality based on user's connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// All video URLs are HLS streams&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;
  &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://stream.mux.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;muxPlaybackId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.m3u8`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;controls&lt;/span&gt;
&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Mux automatically:&lt;/span&gt;
&lt;span class="c1"&gt;// - Detects user's bandwidth&lt;/span&gt;
&lt;span class="c1"&gt;// - Serves optimal quality&lt;/span&gt;
&lt;span class="c1"&gt;// - Switches mid-stream if connection changes&lt;/span&gt;
&lt;span class="c1"&gt;// - Provides smooth buffering&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Progress Tracking Integration
&lt;/h3&gt;

&lt;p&gt;I built a custom system on top of Mux playback:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// VideoPlayer component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;VideoPlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;videoId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;muxPlaybackId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialPosition&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;videoRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCurrentTime&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialPosition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Track time updates&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleTimeUpdate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setCurrentTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;videoRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Auto-save every 15 seconds (debounced to reduce API calls)&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;videoId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trackingTimer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;videoApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateProgress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;videoId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;15000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;trackingTimer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="c1"&gt;// Resume from where user left off&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;videoRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;initialPosition&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;videoRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;initialPosition&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;initialPosition&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;
      &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;videoRef&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`https://stream.mux.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;muxPlaybackId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.m3u8`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onTimeUpdate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleTimeUpdate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;controls&lt;/span&gt;
    &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a YouTube-like experience where users always resume from where they left off.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Metadata Extraction
&lt;/h3&gt;

&lt;p&gt;Mux provides metadata that AyurAI uses for the UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;assetId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Extract key metadata&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// ← Total video length&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                 &lt;span class="c1"&gt;// ← Video dimensions&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frame_rate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="c1"&gt;// ← For quality indicators&lt;/span&gt;
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// AyurAI displays duration on video cards:&lt;/span&gt;
&lt;span class="c1"&gt;// "45:30" (45 minutes, 30 seconds)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Playback ID Strategy
&lt;/h3&gt;

&lt;p&gt;Mux assigns each video a unique &lt;strong&gt;playback ID&lt;/strong&gt;, separate from the asset ID. This is powerful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Asset ID (unique, server-side)&lt;/span&gt;
&lt;span class="nx"&gt;muxAssetId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;abc123def456&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// Playback ID (unique, client-safe)&lt;/span&gt;
&lt;span class="nx"&gt;muxPlaybackId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ji1XhtoywRhdk402DJ9FT3IcQ4Q01HCneqqDm2OwPBdrQ&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// Users only see playback ID in URLs:&lt;/span&gt;
&lt;span class="c1"&gt;// https://stream.mux.com/ji1XhtoywRhdk402DJ9FT3IcQ4Q01HCneqqDm2OwPBdrQ.m3u8&lt;/span&gt;

&lt;span class="c1"&gt;// This means:&lt;/span&gt;
&lt;span class="c1"&gt;// - Asset IDs never exposed to clients&lt;/span&gt;
&lt;span class="c1"&gt;// - Can revoke playback IDs without deleting video&lt;/span&gt;
&lt;span class="c1"&gt;// - Fine-grained access control possible&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. Global CDN Delivery
&lt;/h3&gt;

&lt;p&gt;Mux's infrastructure ensures:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User in India
  ↓
Closest Mux edge node
  ↓
Video streams with &amp;lt;100ms latency
  ↓
Adaptive quality based on connection

User in USA
  ↓
Different edge node
  ↓
Same experience, optimized for region
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AyurAI doesn't worry about CDN setup—Mux handles it.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Real Example: Video Upload Workflow
&lt;/h3&gt;

&lt;p&gt;Here's the complete flow when an admin uploads a wellness video:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Step 1: Admin clicks upload&lt;/span&gt;
&lt;span class="c1"&gt;// Frontend calls: POST /api/admin/videos/upload&lt;/span&gt;

&lt;span class="c1"&gt;// Step 2: Backend creates Mux upload session&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uploads&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;new_asset_settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;playback_policy&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="s1"&gt;public&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;// Returns upload URL&lt;/span&gt;

&lt;span class="c1"&gt;// Step 3: Admin uploads directly to Mux&lt;/span&gt;
&lt;span class="c1"&gt;// (File never touches AyurAI servers)&lt;/span&gt;

&lt;span class="c1"&gt;// Step 4: Backend polls for completion&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;upload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uploads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;uploadId&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;upload&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="s1"&gt;ready&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mux&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asset_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Step 5: Save metadata to database&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;video&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;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ayurvedic Morning Routine&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&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="na"&gt;muxAssetId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;muxPlaybackId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playback_ids&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;thumbnailUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://image.mux.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playback_ids&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="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/thumbnail.jpg`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;isPublished&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="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="c1"&gt;// Emit event&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;topic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video.published&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;videoId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Step 6: Motia triggers downstream events&lt;/span&gt;
&lt;span class="c1"&gt;// - Update search index&lt;/span&gt;
&lt;span class="c1"&gt;// - Notify admin of completion&lt;/span&gt;
&lt;span class="c1"&gt;// - Generate recommended videos&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Netflix-quality video appears in the app within minutes of upload. Zero server infrastructure concerns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Matters
&lt;/h3&gt;

&lt;p&gt;By using Mux beyond just hosting, AyurAI:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Saves bandwidth&lt;/strong&gt; - No video data on my servers&lt;br&gt;
✅ &lt;strong&gt;Saves storage&lt;/strong&gt; - Mux stores, I just reference&lt;br&gt;
✅ &lt;strong&gt;Saves complexity&lt;/strong&gt; - No encoding pipelines to manage&lt;br&gt;
✅ &lt;strong&gt;Saves costs&lt;/strong&gt; - Pay per video delivered, not per storage&lt;br&gt;
✅ &lt;strong&gt;Provides reliability&lt;/strong&gt; - Netflix-grade infrastructure&lt;br&gt;
✅ &lt;strong&gt;Enables features&lt;/strong&gt; - Progress tracking, adaptive streaming, global delivery&lt;br&gt;
✅ &lt;strong&gt;Scales automatically&lt;/strong&gt; - Handle 1 user or 1M users with same infrastructure&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>muxchallenge</category>
      <category>showandtell</category>
      <category>video</category>
    </item>
    <item>
      <title>Midnight ZK Circuit Playground: Web-based IDE to understand Midnight Network</title>
      <dc:creator>Ashita</dc:creator>
      <pubDate>Sun, 07 Sep 2025 12:22:19 +0000</pubDate>
      <link>https://forem.com/itsashita/midnight-zk-circuit-playground-web-based-ide-to-understand-midnight-network-3f6a</link>
      <guid>https://forem.com/itsashita/midnight-zk-circuit-playground-web-based-ide-to-understand-midnight-network-3f6a</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/midnight-2025-08-20"&gt;Midnight Network "Privacy First" Challenge&lt;/a&gt; - Enhance the Ecosystem prompt&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;📌 Summary:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;An interactive playground  that helps developers first test out Midnight zero-knowledge proof circuits with mock circuits that replicate real-world use cases around privacy. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;🔎 Scenarios:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Playground has 3 scenarios: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Confidential Voting&lt;/strong&gt; - Demonstrate private voter credentials while proving eligibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sealed Bid Auction&lt;/strong&gt; - Show how bid amounts remain secret until reveal phase.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anonymous Identity Verification&lt;/strong&gt; - Prove age/eligibility without revealing personal data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each scenario comes with a step-by-step proof generation with detailed explanations.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;🔑 Key Features Implementation:&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Private Input Handling &amp;amp; Double-Entry Prevention -
&lt;/h3&gt;

&lt;p&gt;This code implements a nullifier system - a cryptographic mechanism used to prevent duplicate actions or "double-spending" type problems in various scenarios. &lt;br&gt;
Generates unique identifiers (nullifiers) that can be publicly checked to ensure someone hasn't already performed a specific action, without revealing their actual identity.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;client/src/hooks/useProofGeneration.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Comprehensive nullifier system preventing double submissions

const nullifierCheck = (scenario: string, inputs: Record&amp;lt;string, string&amp;gt;) =&amp;gt; {
  switch (scenario) {
    case 'voting':
      // Prevents same voter ID from voting twice
      nullifier = `voting_${inputs.voter_id}_${inputs.private_credentials}`;
      errorMessage = 'This voter ID has already cast a vote. Double voting is not allowed.';
      break;
    case 'auction':
      // Prevents same bidder from bidding multiple times
      nullifier = `auction_${inputs.bidder_secret}_${inputs.private_bidder_identity}`;
      errorMessage = 'This bidder has already submitted a bid. Multiple bids not allowed.';
      break;
    case 'identity':
      // Prevents duplicate identity verifications
      nullifier = `identity_${inputs.private_ssn}_${inputs.birth_cert_hash}`;
      errorMessage = 'This identity has already been verified. Duplicate attempts blocked.';
      break;
  }
  return { nullifier, errorMessage };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Interactive Circuit Animation -
&lt;/h3&gt;

&lt;p&gt;This is a functional React component that takes data as props and renders a visual node with connection handles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Animation System:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;- Conditionally applies animate-pulse and ring styling when data.isAnimated is true&lt;/li&gt;
&lt;li&gt;- Creates a pulsing effect with a glowing ring around animated nodes&lt;/li&gt;
&lt;li&gt;- Uses Tailwind CSS for smooth transitions (transition-all duration-300)&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Privacy Indicators:&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;- Red dot badge: Small circular indicator in top-right corner with "P" label.&lt;/li&gt;
&lt;li&gt;- Text label: Shows "Private Input" below the node content.&lt;/li&gt;
&lt;li&gt;- Both only appear when data.isPrivate is true.&lt;/li&gt;
&lt;li&gt;- Uses red color scheme to visually distinguish private data.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;client/src/components/CircuitDesigner.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Circuit nodes with privacy indicators and animation support
const CircuitNode: React.FC&amp;lt;CircuitNodeProps&amp;gt; = ({ data }) =&amp;gt; {
  return (
    &amp;lt;Card className={`circuit-node transition-all duration-300 
                     ${data.isAnimated ? 'animate-pulse ring-2 ring-primary/50' : ''}`}&amp;gt;
      &amp;lt;Handle type="target" position={Position.Left} /&amp;gt;
      &amp;lt;Handle type="source" position={Position.Right} /&amp;gt;

      {/* Private data indicator */}
      {data.isPrivate &amp;amp;&amp;amp; (
        &amp;lt;div className="absolute -top-1 -right-1 w-3 h-3 bg-red-500 rounded-full"&amp;gt;
          &amp;lt;span className="text-[8px] text-white font-bold"&amp;gt;P&amp;lt;/span&amp;gt;
        &amp;lt;/div&amp;gt;
      )}

      {/* Privacy labels */}
      {data.isPrivate &amp;amp;&amp;amp; (
        &amp;lt;div className="text-[10px] text-red-500 font-medium mt-1"&amp;gt;Private Input&amp;lt;/div&amp;gt;
      )}
    &amp;lt;/Card&amp;gt;
  );
};

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

&lt;/div&gt;

&lt;h3&gt;
  
  
  3. Privacy-Emphasized UI Components -
&lt;/h3&gt;

&lt;p&gt;The privacy-aware input fields for cryptographic applications automatically masks private text inputs as password fields (showing dots instead of plain text), apply distinctive red styling to visually distinguish sensitive data and include explanatory text reassuring users that their private information "remains encrypted and hidden during proof generation."&lt;/p&gt;

&lt;p&gt;&lt;code&gt;client/src/components/ScenarioSidebar.tsx&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Private inputs with visual encryption

&amp;lt;Input
  type={input.isPrivate &amp;amp;&amp;amp; input.type === 'text' ? 'password' : input.type}
  className={input.isPrivate ? 'border-red-500 bg-red-50 dark:bg-red-950/20' : ''}
  placeholder={input.isPrivate ? 'Private data - encrypted' : ''}
/&amp;gt;

{/* Privacy explanation for each private input */}
{input.isPrivate &amp;amp;&amp;amp; (
  &amp;lt;div className="text-xs text-red-500 mt-1 flex items-center"&amp;gt;
    &amp;lt;span className="w-2 h-2 bg-red-500 rounded-full mr-1"&amp;gt;&amp;lt;/span&amp;gt;
    This data remains encrypted and hidden during proof generation
  &amp;lt;/div&amp;gt;
)}

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

&lt;/div&gt;

&lt;h3&gt;
  
  
  4. Zero-Knowledge Scenarios with Real Privacy Examples -
&lt;/h3&gt;

&lt;p&gt;The scenario configuration file exports an array of three privacy-preserving use cases, each containing complete UI and circuit specifications.&lt;/p&gt;

&lt;p&gt;Each scenario includes multiple components: visual circuit representation with nodes and edges showing data flow through cryptographic operations, step-by-step proof generation process with timing and status updates, circuit code written in Midnight Compact Language demonstrating the actual cryptographic logic, and input field definitions distinguishing between public and private data fields.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Confidential Voting&lt;/strong&gt; scenario demonstrates anonymous voting where private voter credentials and choices are processed through hash functions and nullifier checks to prevent double-voting while maintaining ballot secrecy.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Sealed Bid Auction&lt;/strong&gt; scenario shows how bidders can submit private bids with commitments and range proofs to ensure minimum bid requirements without revealing actual amounts until the reveal phase.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Anonymous Identity&lt;/strong&gt; scenario enables age verification and registry membership checks without exposing personal details like exact age or SSN, using Merkle proofs for membership verification.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;client/src/data/scenarios.ts&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Confidential Voting - Real privacy protection
{
  id: 'voting',
  name: 'Confidential Voting',
  inputs: [
    { label: 'Voter ID', key: 'voter_id', type: 'text', defaultValue: 'voter_12345' },
    { label: 'Private Credentials', key: 'private_credentials', type: 'text', 
      defaultValue: 'SSN:***-**-1234', isPrivate: true },
    { label: 'Secret Nullifier', key: 'secret_nullifier', type: 'text', 
      defaultValue: 'secret_nonce_abc123', isPrivate: true },
    { label: 'Candidate Choice', key: 'choice', type: 'select', 
      options: ['Candidate A', 'Candidate B', 'Candidate C'] }
  ],
  code: `// Midnight Compact Language
circuit ConfidentialVote {
  private input voter_id: Field;
  private input choice: Field;
  private input nullifier_secret: Field;

  public input nullifier_hash: Field;
  public output commitment: Field;

  // Privacy-preserving computations
  let vote_hash = hash(voter_id, choice);
  let nullifier = hash(voter_id, nullifier_secret);
  assert(nullifier == nullifier_hash);

  commitment = hash(vote_hash, nullifier);
}`
}

// Anonymous Identity Verification - Age proof without revealing exact age
{
  id: 'identity', 
  name: 'Anonymous Identity Verification',
  inputs: [
    { label: 'Private Age', key: 'age', type: 'number', defaultValue: '25', isPrivate: true },
    { label: 'Private SSN', key: 'private_ssn', type: 'text', 
      defaultValue: '***-**-5678', isPrivate: true },
    { label: 'Private Birth Certificate Hash', key: 'birth_cert_hash', type: 'text', 
      defaultValue: '0x8a7f...b3c2', isPrivate: true }
  ],
  code: `circuit AnonymousIdentity {
    private input age: Field;
    private input identity_hash: Field;

    // Verify age &amp;gt;= 18 WITHOUT revealing actual age
    assert(age &amp;gt;= 18);

    // Generate anonymous verification token
    anonymous_token = hash(identity_hash, age);
  }`
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;🎓 Educational Impact:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This Playground demonstrates real-world zero-knowledge applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Confidential Voting:&lt;/strong&gt; Proves vote validity without revealing choice or voter identity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private Auctions:&lt;/strong&gt; Enables fair bidding while keeping amounts secret.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anonymous Identity:&lt;/strong&gt; Verifies age/credentials without exposing personal data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-Replay Protection:&lt;/strong&gt; Prevents double submissions across all scenarios.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Video:
&lt;/h2&gt;


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



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

&lt;p&gt;&lt;a href="https://github.com/devandop/MidnightZK-Playground" rel="noopener noreferrer"&gt;https://github.com/devandop/MidnightZK-Playground&lt;/a&gt;&lt;/p&gt;

</description>
      <category>midnightchallenge</category>
      <category>devchallenge</category>
      <category>web3</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>Mem0 application is on Railway</title>
      <dc:creator>Ashita</dc:creator>
      <pubDate>Mon, 11 Aug 2025 12:03:10 +0000</pubDate>
      <link>https://forem.com/itsashita/mem0-application-is-on-railway-3i5g</link>
      <guid>https://forem.com/itsashita/mem0-application-is-on-railway-3i5g</guid>
      <description>&lt;p&gt;If you're reading this article, you're probably wondering what does this even mean. I get the confusion but hopefully I'll be able to explain what my Mem0 and Railway is.&lt;/p&gt;

&lt;p&gt;**&lt;/p&gt;

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

&lt;p&gt;**&lt;br&gt;
Before understanding about Mem0,let's understand the present scenario of AI agents. When a user sends a request to the AI agent, the agent will process the request and send a response to the user without remembering the context of the request in the next session. This can lead to frustration since you would need to generate the same request all over from the previous day. What if there was a better way to deal with this?&lt;/p&gt;

&lt;p&gt;Enter Mem0: An intelligent layer that sits along your LLM, it not only keeps track of all your past interactions  but also stores long term knowledge making your agents more adaptive. With a persistent memory retention,Mem0 cuts the cost of sending repeated requests to LLM.&lt;/p&gt;

&lt;p&gt;When RAG doesn't understand what the user had asked previously, Mem0 does the job of providing continuity to your agent by shaping it's memory. Mem0 is not a wrapper but a memory engine that is capable of deciding what to remember by filtering out irrelevant information.&lt;/p&gt;

&lt;p&gt;Mimicking the way how humans store information, Mem0 supports different types of memory- from remembering previous conversations to building knowledge as time progresses.Mem0 is built to handle multimodal support with an upgraded feature of providing insights across sessions as a Graph Memory.&lt;/p&gt;

&lt;p&gt;Mem0 allows you to do the following memory operations-&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add Memory&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Retrieve Memory&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Update Memory&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delete Memory&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With Add memory, you can store user interactions that can be retrieved for later use. The add operation acts as an entry point for long-term memory knowledge. When a user sends a message, the input is sent to the LLM that extracts facts or decisions and Mem0 API then compares the new information with existing memory to detect for duplication and stores result in a vector database.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;add()&lt;/strong&gt; operation is used in scenarios when a user has introduced a new decision/preference or when a feedback is suggested.&lt;/p&gt;

&lt;p&gt;The Retrieve Memory in &lt;strong&gt;search()&lt;/strong&gt; operation retrieves relevant memory and supports operations such as semantic similarity search and metadata filtering with logic to name a few.&lt;/p&gt;

&lt;p&gt;Updating an exisiting memory such as updating facts is done with the &lt;strong&gt;update()&lt;/strong&gt; operation.Mem0 lets you update a single specific memory or lets you batch updates of up to a thousand memories at once.&lt;/p&gt;

&lt;p&gt;When a memory becomes irrelevant or needs to be removed for privacy, just like update() Mem0 gives you the option of deleting a specific memory or delete multiple memory IDs as a batch using &lt;strong&gt;delete()&lt;/strong&gt; operation. &lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying Mem0 Next.js Chatbot on Railway.com
&lt;/h2&gt;

&lt;p&gt;Mem0 has a ready to use Next.js Companion application that let's you understand how Mem0 API can be used to create an application that better understands user context. You can add more features to improve contextual retention or integrate third-party services to extend its functionality. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Railway.com?
&lt;/h2&gt;

&lt;p&gt;Given the ease with which Railway handles everything for you with minimal configuration, deploying Mem0 Next.js application on the platform was such a cakewalk. &lt;br&gt;
All you have to do is Connect your GitHub repository,add the API keys of Mem0 and OpenAI to Railway's Variable Setting,generate a Railway domain for your application under Public Networking with a port that makes your chatbot public on the internet and watch as Railway does all the magic for you. Railway uses Nixpacks to build and deploy your code even without a Dockerfile.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
