Built for FMCG trade operations
Godam
FMCG trade-operations app for Nepal distributors. Next.js 15 + Supabase/Postgres: party ledgers with VAT/PAN, billing, collections, supplier payments, credit, sauda, godown stock, DSR, and field-visit logging. Built solo. No revenue claim on this page.
Problem
Distributor operations split across spreadsheets: who owes what, what left the godown, which cheque is out, which salesman visited which outlet. The failure mode is not “no app.” It is two numbers for the same party.
The data model has to look like trade ops — parties that are supplier, customer, or both; items with reorder levels; NPR amounts — not a generic CRUD starter.
Constraints
Built solo. The UI is a phone-width shell (max 480px) because DSR and collections are entered in the field.
Roles matter: admin / staff / viewer. Viewers must not alter ledgers.
Architecture
Next.js App Router on Vercel, Supabase/Postgres as the store. Screens map to operations: ledger (parties and items), godown, cash, collections, supplier payments, outgoing cheques, sauda, DSR, field visits, reports.
Party records carry VAT and PAN. Amounts format as NPR. Session roles gate who can insert or update.
There is no LLM in the critical path. Reliability here is referential integrity and role checks, not a prompt.
Reliability / eval
Postgres is the ledger. Client state is a cache of queries, not the books.
Role flags (admin / staff / viewer) are checked before mutations. That is application-level enforcement on top of Supabase auth — not a substitute for row-level policies, which I would tighten.
I have not published a labelled eval for Godam. The honest test is reconciling a day’s collections and godown movement against the rows, not a model score.
Known failure modes
App-level roles vs database policies
If a client bypasses the UI, viewer restrictions only hold if Postgres RLS matches the same rules. I would not defend this in an interview as fully locked down without showing the policies.
No committed eval harness
Unlike Stacksift, there is no golden set of ledger cases. Dual-entry mistakes would be caught by a human reconciling, not by a script.
What I would do differently
- Move invariants into Postgres (RLS, cheque uniqueness, credit vs invoice balance) so the UI cannot be the only gate.
- Add a replayable fixture of a trading day and assert balances — the analogue of eval_labels.json for a ledger.
Stack
- Next.js 15
- TypeScript
- Supabase