Brian Omariba
Start a project →
← All systems
Dossier /05 Food vending operations Live

Planet Nine Bites

A food business is three businesses: the menu, the vendors, and the money.

An operations platform for food vending — one order record followed from the customer’s phone through the vendor to the head-office books.

Category
Operations platform
Role
System design · Backend engineering · Integrations
Stack
NestJS · PostgreSQL · M-Pesa Daraja
Status
Live
01 — Problem

Three audiences, three different jobs, one shared record.

A vending operation is not one system. A customer wants to order in under a minute. A vendor wants today’s list and nothing else. Head office wants to know what was sold, by whom, and whether the money arrived.

Built separately, those three views drift apart, and reconciliation becomes a weekly argument with a spreadsheet.

Order capture
Vendor fulfilment
Stock reality
Payment confirmation
Settlement
Reconciliation
02 — System

One order object, three surfaces onto it.

Each role gets an interface shaped for its job, but all three read and write the same record — so there is never a question of which view is correct.

01Customer

Browses and orders from the storefront.

02Order

Created once, with everything the rest of the chain needs.

03Payment

M-Pesa, confirmed by callback rather than by reading a text message.

04Vendor

Sees only what they must act on now.

05Fulfilment

Status recorded at the point it changes, by whoever changed it.

06Head office

A console over the whole operation rather than a report after it.

03 — Architecture

No SMS anywhere — and that was the point.

The common shortcut in Kenyan commerce software is to confirm payments by scraping M-Pesa SMS notifications. It works until it doesn’t: messages arrive late, get truncated, or land on a phone nobody is watching.

This system removes SMS from the payment path entirely. Daraja callbacks confirm payment directly, server to server, so a payment is an event the system receives rather than a message someone has to read. That single decision removes an entire class of reconciliation bug.

Built as a NestJS monorepo over PostgreSQL, with the admin, vendor and customer surfaces sharing one domain model.

04 — Interface

The storefront.

The customer-facing side is deliberately light — the order is the only thing being asked for.

Planet Nine Bites interface

planetninebites.com — customer storefront. The head-office console is behind authentication at admin.planetninebites.com.

05 — Outcome

What the system changes.

Payment stops being something a human confirms. The order, the fulfilment and the money end up on the same record, so the weekly reconciliation becomes a query instead of an investigation.

Order volume and settlement metrics — to be published with permission