Skip to content

Demo mode

Loading clock…

Milvara

For technical buyers

How a milk subscription actually works

It looks simple until you write it down: recurring rules, one-off changes, vacations, a nightly cutoff and a prepaid wallet all interact. Everything below runs the real engine on this browser's demo data — change something in the app and it shows up here.

01

Rules, not rows

A subscription is stored as a rule: which days, how many on each weekday, from when. A day only becomes a row when it locks — everything before that is worked out on the spot.

02

The resolution pipeline

Every customer's day resolves the same way, in the same order. A vacation beats any change made for that day, and once the day locks the snapshot wins over everything.

03

The 10 PM cutoff

Orders for a day lock at 10 PM the night before. That is the moment delivery rows are written and wallets are charged — once. Running the lock again changes nothing.

04

The pause that starts mid-cutoff

The edge case most builds get wrong: a vacation that starts tomorrow, saved after tomorrow has already locked. The rule moves the start to the first day that can still change, and tells the customer why.

05

Money is a ledger

The wallet balance is never stored. Top-ups, charges and refunds are entries in an append-only ledger and the balance is their sum, so the wallet and the statement can't disagree.

06

Tested like it matters

The rules above are pure functions of state and time, so they are tested directly — every edge case on this page has a test with its name on it.

Unit tests passing in this build

121across 14 test files · Vitest

Counted when the site was built. If one fails, the build stops and nothing ships.

  • Domain engine89 tests · 9 files
  • Seed data9 tests · 1 file
  • Demo store and clock8 tests · 1 file
  • Components and tour8 tests · 2 files
  • Formatting7 tests · 1 file

A few of the test names

  • pause created at 22:30 starting tomorrow is clamped to the day after tomorrow and tomorrow is still delivered and charged
  • is editable until 21:59:59 IST the night before and locked at 22:00:00
  • refunds a not-delivered order exactly once
  • is idempotent
  • catches up every missed night in order after jumping three days
  • reconciles: opening + top-ups + refunds − charges = closing = balance
  • splits an existing rule after the cutoff so locked history keeps old quantities

The domain suite runs again with the machine set to New York time to prove the IST date maths never leans on the server's clock, and Playwright walks the customer, dairy, delivery and tour flows on desktop Chrome and a Pixel 7.

07

Stack

What runs in this demo, and what takes its place for a real dairy.

In this demo

  • Next.js 15 App Router · React 19 · TypeScript
  • Tailwind CSS 4 with shadcn/ui on Radix
  • Zustand, persisted to this browser’s localStorage
  • date-fns with @date-fns/tz — every day is an Asia/Kolkata day
  • Vitest for the engine, Playwright for the flows

In production

  • Postgres for rules, overrides, pauses, the ledger and locked deliveries
  • A nightly Vercel Cron job that runs the 10 PM lock
  • Razorpay UPI for wallet top-ups
  • Gupshup for WhatsApp reminders and receipts
  • Phone OTP sign-in

No database in this demo — the same domain functions run server-side against Postgres in production.

Explore on your own