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.
Case study · Live in production
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.
Architecture
Select any part of the map to see what it does and why it's built that way.
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
Each one trades a little convenience for something the shop can't afford to lose.
01 · Security
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
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
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
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
Four runtime dependencies. No state library and no CSS framework, so there's less to break and less for the next developer to learn.
Hiring for an engineering role, or a business that needs its own site? Let's talk.