Case study
GlowStock
Overview
A private online ledger for one retail store: products, stock, sales, installments, refunds, and expenses with category-level allocations, all in centavo-exact pesos. Owner-only, no payments, no customer accounts.
Problem
A store owner was running sales, installments, refunds, and category-level profit in a notebook. Stock went negative on paper, discounts never reconciled to the centavo, and asking how much a category actually netted meant reconstructing history by hand.
Approach
A single-owner ledger rather than a POS. Sales are atomic multi-product transactions that deduct stock immediately and snapshot the price and category-hierarchy path at sale time, so history never rewrites when the catalog changes. Installments, refunds, and voids keep a buyer ledger; expenses allocate to category nodes with roll-ups; and hierarchies go up to eight owner-named levels. Money is stored as integer centavos with a deterministic remainder rule so line items always reconcile to the total.
Architecture
npm workspaces: a React 19 PWA client and a Hono Worker bundled with esbuild to a _worker.js serving the same origin, over Turso with Drizzle ORM. DB-level CHECK constraints back every financial rule, idempotency keys cover sales, payments, stock movements, and expenses, and the first owner bootstraps through a one-time setup token under Better Auth. Email is a transactional outbox with 30-second leases, three attempts, and capped backoff feeding Resend at its 2 req/s limit. Tab sync uses a one-row cursor plus BroadcastChannel and adaptive 30s/120s polling, about 0.003% of Turso's monthly quota.
Challenges
Centavo-exact category accounting: discounts distribute proportionally across lines with a remainder rule, and hierarchical expense allocation has to exclude parent and sibling costs from a child's net income while still showing what was excluded. A naive 10-second poll would have burned an estimated 388 million row reads a month, so sync shrank to one row and activity-aware polling. Emails lost to Resend 429s are what forced the outbox in the first place.
Results
Live since October 2026: 11 migrations without data loss, including one surgical conversion of legacy fulfillment records into sale movements, 26 automated financial and performance tests, Lighthouse 100 on accessibility and best practices, and free tiers end to end.