In production · partial launchClient project

Kandy's Treats

An ordering platform and operations back office for Kandy's Treats. Customers build a plate, pay by card or wallet and track the order; staff run orders, menu, inventory, finance and the team from one admin console.

My role
Full-stack development, payments integration, database design and migration
Client
Kandy's Treats, a Nigerian kitchen in Ado-Ekiti
Category
Web application, Commerce
Kandy's Treats home page with a plate of jollof rice and chicken, a food search box and delivery information.
Customer storefront. Local build; the menu renders from the bundled snapshot of the real menu.

01

Overview

Kandy's Treats sells Nigerian food by the scoop: you build a plate from rice, proteins and sides, choose delivery or pickup, and pay. The platform covers that customer journey and the work behind it.

It started on Firebase. The current version runs on Supabase and PostgreSQL, with the storefront kept as fast, build-free HTML, CSS and JavaScript.

  • HTML
  • CSS
  • JavaScript
  • Supabase
  • PostgreSQL
  • Row Level Security
  • Edge Functions
  • Paystack
  • Firebase (earlier backend)

02

The problem

Money is involved at every step: prices, packaging fees, coupons, delivery fees, wallet balances and refunds. None of those figures can be trusted if they are calculated in the browser.

The kitchen also needed more than a checkout. Staff take orders, track stock, close the day, manage the team and answer customers, and those jobs had to sit on the same data.

03

Approach

Orders are created and priced only on the server. Checkout re-reads every line from the menu, recalculates fees and coupons, and writes the order inside a database function. The browser is never granted insert or update rights on orders, wallets or payment tables.

Payments are initialised server-side and confirmed by verification plus signed webhooks, so a closed tab or a retried callback cannot double-credit a wallet.

I moved the backend from Firebase to Supabase in versioned SQL migrations, keeping old menu IDs resolvable so existing links still work.

04

Architecture

Storefront
Static HTML, CSS and vanilla JavaScript with no build step. Paints from a bundled menu snapshot, then refreshes from live data.
Database
Supabase PostgreSQL with Row Level Security and column-level grants. Over 80 versioned migrations.
Server logic
SECURITY DEFINER functions for checkout, wallet movements and admin actions; Supabase Edge Functions for Paystack, email and push.
Payments
Paystack, initialised on the server and confirmed by verification and webhooks. Card details never touch the site.

05

Key features

  • Build-your-plate ordering

    Per-scoop pricing, proteins and sides as their own lines, packaging rules, coupons, and delivery or pickup.

  • Wallet

    Fund, pay and receive refunds through a ledger of wallet transactions rather than an editable balance.

  • Order tracking

    Order statuses with history and transition rules, notifications and push alerts.

  • Admin console

    Orders, menu and catalogue, customers, support conversations, announcements, careers and settings.

  • Inventory and finance

    An append-only inventory ledger, ingredients, end-of-day staff reports, sales reporting and a finance audit trail.

  • Team and partners

    Staff invitations, role tiers, suspension, and partner referrals with order commission.

The full menu with category filters and dish cards showing prices per scoop.
Menu with category filters and per-scoop pricing.

06

Challenges

  1. Prices the browser cannot change

    Problem

    A client-calculated total can be edited before it is submitted.

    What I did

    The server recomputes every figure from the menu table inside the same transaction that creates the order, and the client is denied write access to the tables involved.

  2. Migrating a live business

    Problem

    Moving from Firebase to Supabase risked breaking links, accounts and history the kitchen relies on.

    What I did

    A staged migration: schema and policies first, then features, with legacy Firebase IDs stored alongside new rows so old menu links and accounts still resolve.

  3. Showing stale prices

    Problem

    A customer could see a cached price for a dish that had been repriced or sold out.

    What I did

    Pages render the snapshot immediately, then repaint from live data, and the basket drops lines that no longer exist before checkout.

07

Where it stands

Built

  • Customer storefront, accounts, checkout, wallet and Paystack payments
  • Admin console for orders, menu, inventory, finance, staff and support
  • Firebase to Supabase migration of the core data and logic

The platform went to a partial launch in September 2026 and is still being refined with the kitchen.

↑ ↓ to move · Enter to openAMIGODEV