Paste this:

## Inspiration
My local kirana / sweet shops take all orders on personal WhatsApp in messy Hindi/Hinglish — `bhai 500g sugar dena`, `10 laddu chahiye`. Everything goes into a notebook, profit math is manual, and every customer needs a reply. I wanted a munim that lives on one phone, in Hindi, for Rs. 0.

## What it does
Link WhatsApp once with a pairing code. Every incoming message becomes a structured order — customer, item, qty/unit, cost, profit %, profit Rs., total — shown in a Hindi dashboard with revenue/profit stats, catalog auto-pricing, pending-price queue, reports, and an automatic Hindi confirmation reply to the customer (price only, cost/profit stay private).

## How I built it
- **3 engines, same flow:** PC (`src/bot.js`), Render (`server/server.js`) on zapo-js + SQLite, and on-phone Go bridge (`mobile-engine/` — whatsmeow via gomobile) + Android foreground service + `LocalApi` on `127.0.0.1:3000`.
- **Parsing:** Poolside AI first (`poolside/laguna-xs-2.1` → order JSON), regex fallback. Phone is regex-only offline (`JavaParser.java`, 4th copy of `src/parser.js`).
- **Pricing math:** `profit = cost * pct / 100`, `total = cost + profit`, backfilled either way. Catalog fills missing prices with unit conversion (kg↔g, ml↔l, pcs, `priceQty` for "100ml for Rs. 20").
- **Names:** phone contacts via READ_CONTACTS matched on last-10-digits, LID→phone via `remoteJidAlt/SenderAlt`.
- **Dashboard:** same Hindi HTML/JS assets on PC + in-APK, 3 themes, offline SVG reports.

## Challenges
- **Baileys pairing died** (Apr–Jul 2026 protocol change rejected `companion_finish` crypto). Migrated everything to zapo-js; pairing worked again.
- **Main number 429 rate-limited** — number-scoped, every retry resets the clock. Quarantined it for days, it paired later.
- **No cloud works** — Render/Koyeb egress IPs get WebSocket-blocked by WhatsApp edge. That's why I built the on-phone engine.
- **Phone bugs:** log-forwarder mutex deadlocked pairing-code minting (fixed with `atomic.Value`), empty contact table poisoned the cache (only cache non-empty), bare `500g sugar` had no intent word so regex dropped it (added bare-order rule).
- **Parser ×4 drift** — same regex in Node, server, dashboard JS, and Java. Closed gaps together: `pc` unit, bare numbers with intent, strip `dena/dein/deo`.

## What I learned
WhatsApp protocol debugging from logs, Go→Java via gomobile, Android FGS + battery-exemption reality, and that offline-first beats cloud when infra budget is zero.

Built With

Share this project:

Updates

Submission history