Case study · Live in production

Vault Tech: a storefront the owner runs without me.


A Kampala electronics shop needed its whole catalogue online, phones to laptops with prices in UGX, and a way to update it without calling a developer. I designed, built and deployed it end to end.

At a glance

Products live
100+
Database tables
5
Role
Solo
Checkout
None
The Vault Tech homepage: flagship phones in stock in Kampala, with search and enquiry buttons
The live homepage. Every call to action leads to an enquiry, not a cart: that's how this shop sells.

Architecture

How a request moves through the system.

Select any part of the map to see what it does and why it's built that way.

Visitor's phone

Most visitors arrive on a mid-range Android phone over mobile data. That set the performance budget: self-hosted fonts, compressed images, and no heavy UI framework on top of React.

Mobile first · UGX prices · WhatsApp enquiries

Key decisions

Three calls that shaped the build.

Each one trades a little convenience for something the shop can't afford to lose.

01 · Security

Two independent locks

Row-level security alone trusts any signed-in user. I added an admin allowlist in the database and disabled public sign-ups, so a stray account can sign in but can never change a price.

02 · Reliability

Never a blank page

Marketing content falls back to a built-in copy if the database fails. Products deliberately don't: showing an old price to a real buyer is worse than showing an error.

03 · Performance

Images sized for phones

Uploads are compressed to WebP at most 1200px in the browser, and every product also has a 640px card copy. An asset check script flags any image that's missing its card version.

What went wrong

51 products, silently missing.

I added a batch of computers and audio products through a database migration. The code was merged, the site deployed, and everything looked fine. But a migration file isn't live until it runs against the production database, and this one never had. For a while, 51 products existed in the repository and nowhere on the site.

What I changed: every migration now records the date it was applied, and each one is verified against the live API with the public key before I call it done. Merged and live are now two separate checks.

The lesson carried over to everything I ship: deployment isn't the finish line; verified behaviour in production is.

Stack

Deliberately small.

Four runtime dependencies. No state library and no CSS framework, so there's less to break and less for the next developer to learn.

  • React 19
  • TypeScript
  • React Router 7
  • Vite
  • Supabase JS
  • PostgreSQL
  • Row-level security
  • Supabase Storage
  • Vercel
  • Plain CSS design tokens

Need something like this built?

Hiring for an engineering role, or a business that needs its own site? Let's talk.

Get in touch