Portfolio ProjectFood / subscription commerce

Cadence Kitchen

Weekly meals, on your rhythm.

Cadence Kitchen is a meal-plan subscription product: subscribers pick a plan, choose meals each week against a cut-off, and skip or pause without calling anyone. An operations console covers production, delivery slots, MRR and churn. Built as a React SPA over a modular Express and MongoDB API.

  • React.js
  • TypeScript
  • React Query
  • Node.js
  • Express.js
  • MongoDB
  • REST API
Subscriber dashboard. Interface designed and built by Vikrant

Overview

Business problem
Meal-kit style subscriptions punish flexibility. Skipping a week means emailing support, plan changes arrive with surprise charges, and nobody can see how a week of meals adds up nutritionally. Operations, meanwhile, get production numbers that are still moving after the kitchen has started.
Product objective
Make the subscription itself the product: every state change (skip, pause, switch plan) is self-serve, predictable and previewed in pounds before it is confirmed, with a hard cut-off the kitchen can plan around.
Target users
Busy professionals and families in the UK who want planned, portion-controlled meals; the kitchen, delivery coordinators and admins who run production and subscriptions.
Solution
A subscriber app built around a week strip and macro rings, a subscription service modelled as an explicit state machine, billing behind a provider abstraction, and an admin console that reads the same data the kitchen produces from.

Project classification

Project type
Subscription SaaS · Web application
Industry
Food / subscription commerce
Frontend
React SPA (TypeScript) with React Query for server state
Backend
Modular Express API with a subscription state machine
Database
MongoDB (documents per subscription, delivery and invoice)
Architecture
SPA, REST API, domain services, scheduler, provider webhooks

User roles

  • Subscriber
  • Kitchen / Operations
  • Delivery Coordinator
  • Admin

My role

  • Product and information architecture for the subscriber app and admin console
  • React and TypeScript frontend, including server-state handling with React Query
  • Express API design: modular services, validation, error envelope
  • MongoDB schema design for subscriptions, deliveries and invoices
  • Subscription lifecycle and billing-event handling designed as a state machine
  • Role-based access for subscriber, operations, delivery and admin

Key features

  • Subscriber dashboard. Interface designed and built by Vikrant

    A dashboard built around the next delivery

    The subscriber lands on one answer: what is coming, when, and what is in it. A week strip shows each delivery as delivered, upcoming or skipped, macro rings summarise the week, and the cut-off countdown makes the edit deadline obvious without a help page.

  • Week menu picker. Interface designed and built by Vikrant

    Week menu picker with live nutrition

    Meals are chosen per delivery against the plan's meal count. Calories, protein, carbs and fat update as selections change, and dietary tags and allergens are visible on each card, so the choice is informed rather than just filled.

  • Manage subscription. Interface designed and built by Vikrant

    Skip, pause and change plan, self-serve

    Every lifecycle action shows its consequence before it commits: the next charge date, any credit or proration, and the cut-off after which a delivery is locked. Skipping a week and pausing for a month are different actions with different effects.

  • Billing. Interface designed and built by Vikrant

    Billing that explains itself

    Upcoming charge, payment method, and invoice history with statuses, including a failed payment with its retry schedule. Card details are handled by the payment provider; the app stores only a reference and display metadata.

  • Operations overview. Interface designed and built by Vikrant

    Operations overview for the kitchen

    Production counts per meal for the next cut-off, delivery slot fill rates, and exceptions (past-due or changed orders) on one screen. Numbers are derived from locked selections, so the kitchen plans from what will actually ship.

  • Analytics. Interface designed and built by Vikrant

    Subscription analytics: MRR and churn

    Admins see recurring revenue movement, churn and a plan mix. Churn is split by reason captured in the cancel flow, so the product team can tell price-driven exits from delivery or menu issues.

Also in the product

  • Weekly and monthly plans: high-protein, vegetarian, fitness and family
  • Week menu picker with live macro totals and an edit cut-off
  • Pause, skip and change-of-plan with a clear billing preview
  • Delivery scheduling against courier slot capacity
  • Invoices, payment method and retry status
  • Nutrition summary per week
  • Admin: subscribers, plans, meals, production counts, MRR and churn

User flow

  1. Browse plans and compare meals per week and price
  2. Choose a plan, delivery address and slot, then pay via the payment provider
  3. Pick meals for the next delivery before the Tuesday cut-off
  4. Receive delivery in the chosen slot; see the week's nutrition summary
  5. Skip a week, pause, or switch plan from Manage with a billing preview
  6. Resume automatically on the chosen date, or cancel with a reason

Technical architecture

  1. React SPA (TypeScript, React Query)
  2. REST API (Express, validation, auth middleware)
  3. Subscription service (state machine)
  4. Billing service and webhook handler
  5. Scheduler (cut-off lock, renewals, retries)
  6. MongoDB
  7. Payment provider, email, courier slots

Database and backend

Subscription state machine

  • States: active, paused, past_due, cancelled. A skipped week is recorded as a PauseEvent on one delivery, not a subscription state.
  • Transitions are explicit and guarded: active to paused (with resume date), paused to active (scheduled or manual), active to past_due (payment failed), past_due to active (retry succeeded), any to cancelled (with reason).
  • Each transition writes an append-only event, so history and analytics replay from the same source.

Billing and invoices

  • Billing sits behind a provider interface; the app only knows customer and payment-method references.
  • Webhook events are verified, stored by provider event id and processed once, so retries and replays are safe.
  • Plan changes create a proration line based on days remaining in the billing period; the preview and the invoice use the same calculation.
  • Failed payments follow a retry schedule before moving the subscription to past_due.

Deliveries and cut-off

  • Each delivery has a cut-off timestamp; the scheduler locks selections at that moment and writes the production snapshot.
  • Delivery slots carry capacity; reservation uses an atomic conditional update so a slot cannot oversell.
  • Locked deliveries reject edits at the service layer, not only in the UI.

API and data

  • REST resources: plans, meals, subscriptions, deliveries, invoices, plus an admin namespace for operations.
  • Zod schemas validate every request; one error envelope with machine-readable codes.
  • MongoDB collections with indexes on subscriber, next-delivery date and status; invoices and events are immutable once written.
  • Role checks (subscriber, operations, delivery, admin) enforced in middleware, with subscriber data scoped by owner.

Challenges and solutions

  • Subscription lifecycle: active, paused, skipped and past due overlap in confusing ways.

    Modelled subscription status as a small state machine with guarded transitions and kept per-delivery skips as separate events. The UI reads allowed actions from the API instead of re-deriving rules.

  • Edits arriving after the kitchen has started production.

    A scheduler locks each delivery at its cut-off and writes a production snapshot; the service rejects later edits with a specific error that the UI turns into a clear message and the next editable delivery.

  • Proration when a subscriber changes plan mid-cycle.

    One pure function computes credit and charge from days remaining, used by both the preview endpoint and invoice creation so the quoted amount always matches the bill. Covered by unit tests on edge dates.

  • Billing webhooks that arrive twice, late or out of order.

    Events are stored by provider event id with a unique index and handled idempotently; state changes check the current state before applying, so a stale event is acknowledged and ignored.

  • Delivery slot capacity under concurrent changes.

    Slot reservation is a single conditional update that only succeeds while the booked count is below capacity, avoiding read-then-write races without a separate lock service.

  • A responsive subscriber UI that never shows stale delivery state.

    React Query keys per delivery with targeted invalidation after each mutation, optimistic updates for menu picks that roll back on a rejected cut-off.

Results

  • Skip, pause and plan changes are self-serve flows with a billing preview before confirmation.
  • Lifecycle rules live in one service, so UI, scheduler and webhooks cannot disagree.
  • Cut-off locking gives the kitchen a stable production snapshot to plan from.
  • Idempotent billing handling makes provider retries safe by design.

Qualitative outcomes only; no usage or revenue figures.

Visual identity

  • Primary #1B1F3B
  • Secondary #2BB673
  • Accent #FF7A1A
  • Background #F6F7FB

DM Sans for UI and headings, DM Mono for nutrition values. Rounded wordmark with a rhythm-wave glyph. Top-nav consumer app, rounded cards, macro rings, week strip.

  • Portfolio ProjectAI / automation

    AgentForge

    Build, ground and monitor AI agents with RAG, tools, a testing playground and usage tracking.

    • Next.js
    • React.js
    • TypeScript
    • Node.js
    • Laravel
    • PostgreSQL
    • pgvector
    • RAG
    • LLM APIs
    • REST API
    • Webhooks
  • Portfolio ProjectHealthcare

    CareBridge

    Clinic portal with appointments, records and role-based access for five user types.

    • React.js
    • Laravel
    • PHP
    • MySQL
    • REST API
    • Sanctum
    • RBAC