Vishal ShahAI Generalist← Back to the work
CASE STUDY · FOOD DELIVERY · LIVE DEMO

One platform. Four portals. An assistant that acts on live data.

Fresh & Quick is a full-stack delivery platform built from scratch. It joins web and phone apps, a Postgres database with vector search, workflow automation, an AI assistant and Google Maps routing.

🛡️ A working demo. Payments are mocked and no real money moves.

4
role-gated web portals
77
seeded stores, 11 categories
11
n8n workflows
160
knowledge chunks in pgvector

The goal 🎯

Build a working delivery marketplace end to end. It should cover customers, store owners, delivery partners and admins, on web and phone, and automate the hand-offs between them.

The scope 🧩

77 seeded stores across 11 categories: restaurants, grocery, pharmacy-style health, pet, flowers, electronics and more. All are browsable, orderable and trackable through one experience.

Architecture at a glance 🏗️

Clients talk to Next.js API routes. The routes own all writes to Postgres. n8n reacts to database events and calls back through internal routes.

System architectureWeb and phone apps call Next.js API routes, which read and write Supabase Postgres. Postgres fires webhooks to n8n, which calls back through internal routes and sends Gmail. The API runs Ask Zippy, which uses Claude and pgvector retrieval. Google Maps serves the browser.🖥️ Web app📱 Phone app🧱 Next.js API routes🗄️ Supabase Postgres🗺️ Google Maps🤖 Ask Zippy⚙️ n8n workflows✉️ GmailNext.js · TypeScript · TailwindReact Native · ExpoService key stays server-side/api/internal/* + shared secretAtomic checkout functionAuth · Storage · RealtimeRow-level security per rolepgvector + HNSW indexKnowledge and catalog chunksOrders · payments · storesPlaces · Geocoding · RoutesPins, ETA and road routeClaude tool loop, 12 toolspgvector RAG + OpenAI embeddings11 workflows on DB webhooksIn-app fallback if n8n is downHTTPSHTTPSDB webhookinternal routeschatmaps on web + phone

One order, end to end 🛵

  1. STEP 1

    Customer checks out

    One atomic Postgres function writes the order, items and payment.

  2. STEP 2

    n8n reacts

    A database webhook fires. The mock payment resolves and the vendor is notified.

  3. STEP 3

    Vendor accepts

    The kanban board moves the order. n8n emails the customer.

  4. STEP 4

    Partner assigned

    The nearest online partner is picked, then reports its position.

  5. STEP 5

    Customer tracks

    The map shows the road route, distance and a driving-time estimate.

  6. STEP 6

    Delivered

    The courier animation completes the order. Delivered and review emails follow.

How each layer works 🔧

Frontend: web and phone

Next.js App RouterTypeScriptTailwind CSSReact NativeExpo SDK 57
  • One Next.js codebase serves four portals: customer, vendor, delivery partner and admin. Each has its own sign-in and navigation shell.
  • The phone app (React Native + Expo) covers the customer, delivery partner and a small admin screen. It uses the same backend and API routes as the web app.
  • An account made on the web signs in on the phone. An order placed on one surface shows on the other.
  • Shared logic, such as tracking and distance math, is kept byte-identical between web and phone. A parity test fails if the two drift apart.

Backend and database

Next.js API routesSupabase (self-hosted)PostgresRow-level securitySupabase AuthDocker
  • Every data-changing action goes through a server-side API route. The privileged service-role key never reaches the browser.
  • Reads that are safe for a user to make go straight to Supabase, guarded by row-level security policies scoped per role and per table.
  • Checkout runs as one Postgres function, so the order, its items and its payment record are written together or not at all.
  • One role column drives which portal a user lands in. New customers wait for admin approval before they can sign in.
  • The whole stack runs in local Docker containers, which keeps running cost at zero.

Vector database and RAG knowledge base

pgvectorHNSW indexOpenAI text-embedding-3-small1,536 dimensions
  • The vector store lives inside the same Supabase Postgres. There is no separate hosted vector service.
  • The how-to knowledge base is a folder of Markdown guides. It is split by heading, hashed and embedded, and only changed chunks are re-embedded. Today it holds 160 chunks.
  • A second index holds store and dish names, descriptions and cuisines. It never stores prices, fees or open status, so those are always read live.
  • Retrieval filters by the caller’s role. A customer sees customer guides; a vendor, partner or admin sees their own.
  • n8n keeps the indexes fresh: one workflow re-ingests the knowledge base, another syncs the catalog nightly.

Ask Zippy, the AI assistant

Claude (Anthropic SDK)Tool-calling loopStreaming repliesRate limits
  • Zippy answers how-to questions from the knowledge base and names the guide each answer came from. If the guides do not cover a question, it says so.
  • It looks up stores, menus, prices, options and open status from live data, and a signed-in customer can ask about their own orders.
  • Twelve tools back it: catalog lookups, order lookups and cart and checkout actions. The loop is bounded to four tool rounds per question.
  • Zippy proposes cart changes as cards. Nothing changes until the customer taps Confirm. It never places, pays for or cancels an order.
  • Identity comes only from the verified session. Signed-in users get 10 questions a minute and 60 a day by default. Each tool group has a kill switch.
  • A scripted evaluation scored 46 of 47 answers correct at the last recorded run. A second check compares answers to the database.

n8n workflow automation

n8n (self-hosted)Postgres database webhooksGmailInternal API routes
  • Eleven workflows react to database events instead of polling. A trigger function on the orders and payments tables posts to n8n when a row changes.
  • They resolve the mock payment, notify the vendor, assign the nearest online delivery partner and email the customer on acceptance and on delivery.
  • About an hour after delivery, one workflow emails a review request. Others handle registration approval emails, Zippy re-ingestion and chat retention.
  • n8n calls back into the app through internal routes protected by a shared secret header.
  • Every checkout-critical flow has an in-process fallback. If n8n is down, checkout still completes, only slower.

Google Maps: addresses, live tracking and drive time

Maps JavaScriptPlacesGeocodingRoutes
  • The location picker uses Places search, “use my current location” and a draggable pin. If Maps fails, the page falls back to typed coordinates.
  • Sign-up geocodes the address on the server before it creates the account. A vague or unknown address is refused.
  • All 77 stores have real geocoded Mumbai addresses, so distances and nearest-first ordering use real locations.
  • The order page draws the road route and shows text like “About 23 min · 8.3 km by road”. The time is driving time without live traffic.
  • Route requests fire only when the partner moves more than 150 m and 30 s have passed. A failure backs off for 60 s and the page falls back to a straight dashed line.
  • If a partner’s last ping is over five minutes old, the page shows “Last seen” and no estimate rather than a stale figure.

How it was built: MCP-driven development

Claude CodePlaywright MCPClaude in ChromeFigma MCPRefero MCP
  • The platform was built with Claude Code, using Model Context Protocol (MCP) servers as working tools.
  • Playwright MCP and Claude in Chrome drove the real app in a browser for live checks and manual screenshots.
  • Figma and Refero MCP servers fed the design work for the visual refreshes.
  • Each feature went through a written spec, a plan, tests and a review before merge.

The 11 n8n workflows ⚡

#WORKFLOWWHAT IT DOES
01Order placedNotifies the vendor once payment succeeds
02Payment mock confirmationResolves the demo payment
03Restaurant status changeNotifies, and emails the customer on acceptance
04Delivery partner assignmentAssigns the nearest online partner
05Delivery status propagationDelivered email, 20 s fallback, review request after 1 h
06Zippy knowledge ingestionRe-embeds changed guides
07Zippy catalog syncNightly store and dish index refresh
08Zippy chat retentionDeletes chats idle for 30 days
09Auto order flowDemo mode: moves orders through each step
10Notify routerRoutes notifications
11Registration eventsEmails admin and customer on sign-up decisions

What I learned 💡

  • Test a third-party SDK in a real browser with the real key. The Maps work passed all unit tests and still crashed the order page twice on the first live run.
  • When a shared data model gains a field, review every role-scoped route that spreads it. New delivery-address coordinates would have leaked to partners for orders that were not theirs.
  • A geocoder returning “OK” is not proof of a real address. Gibberish street names still came back OK, so the parser now accepts only precise matches.

Honest limits 🧾

  • This is a local demo build with mocked payments. No real money moves.
  • The drive-time estimate ignores live traffic. The phone map shows a straight line only, with no road route.
  • The Gmail steps need a connected Gmail credential. Without it, those branches fail and the order is unaffected.
  • Public-launch hardening was deliberately dropped. The platform stays local.

Want something like this for your process? ⏳

Send it over. I'll reply with how I'd build it.