A voice-first CRM co-pilot for Indian small businesses. Built on Gemma 4. Submitted to the Kaggle Gemma 4 Good Hackathon, Digital Equity track.
The owner records a 10-second voice note in Telugu, Hindi, or English, photographs the customer's car, and Saathi turns it into a tracked customer plus a draft WhatsApp follow-up — approved and sent in one tap.
The pilot is a car detailing studio in Hyderabad. The architecture generalizes to any micro-business that runs on a phone and lives on WhatsApp.
Demo viewport. Saathi is a mobile-first PWA — the same React code renders on iOS Safari, Android Chrome, and desktop browsers. The submission video and the README screenshots are recorded from Mac Safari at a 390 × 844 px viewport (Develop → Responsive Design Mode → iPhone 15 Pro), so judges can clone the repo and reproduce every pixel of the demo locally. See
docs/SUBMISSION.mdfor the deployment-shape rationale.
Today · Voice intake · Customer detail · Draft Review with the live Gemma 4 tool-call trace
The 90-second submission video is at video/output/submission.mp4. The build pipeline that produced it (screenshots, voiceover, music bed, subtitle overlays, ffmpeg stitch) is fully reproducible — see video/build.sh.
| Live PWA | https://saathi-crm.vercel.app |
| Submission write-up | docs/SUBMISSION.md |
| License | Apache 2.0 (matches Gemma 4) |
git clone https://github.com/JagadeepPortfolio/saathi-crm
cd saathi-crm
npm install
cp .env.example .env.local # fill in keys per below
npm run devOpen http://localhost:3000 in Safari. To see exactly what judges see in the video, open Develop → Enter Responsive Design Mode → iPhone 15 Pro. Try Today → Customers → pick Ramesh → Draft follow-up. Append ?demo=1 to any URL to see the live Gemma 4 → Twilio function-call trace.
-
Supabase — create project at supabase.com, copy URL and secret key (
sb_secret_*, not the publishable one) to.env.local:NEXT_PUBLIC_SUPABASE_URL=https://...supabase.co SUPABASE_SERVICE_ROLE_KEY=sb_secret_...Apply schema (paste into the Supabase SQL editor or use psql):
psql <connection-string> < supabase/schema.sql psql <connection-string> < supabase/policies.sql psql <connection-string> < supabase/seed.sql
Then create the storage buckets:
npx tsx scripts/setup_storage.ts
-
Gemma 4 + whisper.cpp — local on a Mac M1/M2 or better:
brew install ollama whisper-cpp ffmpeg ollama pull gemma4:e4b mkdir -p models curl -L -o models/ggml-large-v3-turbo.bin \ https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin ollama serve &Default endpoint
http://localhost:11434is what the adapter targets. SetGEMMA_ENDPOINT_URLto a Cloudflare Tunnel URL when serving the dev mac to a remote iPhone. -
Twilio WhatsApp Sandbox — sign up at twilio.com, open the WhatsApp Sandbox, send the
join <phrase>message from your own iPhone to verify it as a recipient. Then:WHATSAPP_PROVIDER=twilio TWILIO_ACCOUNT_SID=AC... TWILIO_AUTH_TOKEN=... TWILIO_WHATSAPP_FROM=whatsapp:+14155238886 WHATSAPP_TEST_RECIPIENT=+91XXXXXXXXXX # your iPhone in E.164The
WHATSAPP_TEST_RECIPIENTenv var is dev-only — Twilio Sandbox can only send to verified recipients, so we override the seeded customer phones with your iPhone for end-to-end testing. -
Optional — switch to mock WhatsApp for UI-only iteration without firing real messages:
WHATSAPP_PROVIDER=mock
Two test scripts exercise the full pipeline against included samples (samples/ramesh_te.m4a, samples/swift.jpg):
# Day 2 acceptance gates: Telugu ASR, Gemma vision + tool calling, generation, latency
npx tsx scripts/test_pipeline.ts
# Day 3 integration: full /api/intake including DB writes
npx tsx scripts/test_intake.tsapp/ Next.js 16 App Router
page.tsx Today screen
customers/ list + detail + edit + draft state machine
record/ full-screen intake state machine
api/
intake/route.ts POST audio + photo → ASR → Gemma → DB
customers/[id]/route.ts GET / PATCH
visits/[id]/route.ts PATCH
draft/route.ts POST customerId → Gemma drafts in language
send/route.ts POST text → Twilio fires WhatsApp
whatsapp/webhook/route.ts Twilio status callback handler
manifest.ts PWA manifest
not-found.tsx, error.tsx Saathi-Saffron 404 + error boundary
components/
MicCapture.tsx iOS-Safari-aware getUserMedia + MediaRecorder
PhotoCapture.tsx file input with capture=environment
StatusTicker.tsx honest progress per docs/ANTI_SLOP.md
ToolCallLog.tsx demo-mode function-call trace (?demo=1)
BottomBar.tsx, CustomersList.tsx
lib/
ai/ gemma + mock adapters, tools schema, prompts
asr/ whisper.cpp subprocess runner
db/ Supabase server client + scoped helpers
whatsapp/ twilio + mock adapters, provider selector
i18n/ hand-written EN / HI / TE strings
intake.ts Flow 1 orchestrator (uploads → ASR → Gemma → DB)
types.ts shared types
supabase/ schema + policies + 8-customer demo seed
scripts/
setup_storage.ts idempotent bucket bootstrap
test_pipeline.ts Day 2 acceptance gates harness
test_intake.ts Day 3 integration test (writes to DB)
samples/
ramesh_te.m4a sample 25s Telugu+English code-mixed clip
swift.jpg sample car photo
docs/ spec-driven artifact pack — read this first
The artifact pack in docs/ is the source of truth. Read order:
docs/SUBMISSION.md← judges read thisdocs/PRD.md,docs/SPEC.md,docs/ARCHITECTURE.mddocs/WORKFLOWS.mddocs/GEMMA_INTEGRATION.md— the model setup, thethink:falseflag, capability tradeoffsdocs/AI_AGENT_SPEC.md— system prompts and tool JSON schemasdocs/DATA_MODEL.mddocs/UI_UX_SPEC.md— Saathi Saffron tokensdocs/ANTI_SLOP.md— non-negotiable UI/UX rulesdocs/TASKS.md— day-by-day execution logdocs/TEST_PLAN.md— acceptance gatesdocs/DEMO_SCRIPT.md— 90s submission video script
Apache 2.0 — see LICENSE. Same as Gemma 4.



