I Rebuilt an Entire Restaurant Ordering System in 5 Days — Here's How
I Rebuilt an Entire Restaurant Ordering System in 5 Days — Here's How
Last Thursday I sat down to replace a live restaurant's entire tech stack. By Monday it was done. One person. Five days. Three independent apps, a full API, 63K orders migrated, and the restaurant never stopped taking orders.
That sounds made up. I get it. But the tools we have now make this kind of velocity real — and I want to break down exactly how so you can do it too.
The Problem
A single-location restaurant had been running on an aging Node.js backend with scattered frontend clients — kiosks at the front window and drive-thru, a mobile app for preorders, and a staff admin panel. All of it was getting creaky. The business wanted a clean slate.
The catch: everything had to keep running. You can't tell customers their ordering app is down while you rebuild.
The Architecture Decision That Made It Possible
Instead of doing this incrementally, I went all-in: rebuild everything at once. Rails 8.1 backend, React Native mobile app, React web admin — three independent projects, all hitting the same API.
This sounds reckless. It was only slightly reckless because of one key constraint: since all four clients (front-window kiosk, drive-thru kiosk, mobile app, website) were being rebuilt anyway, I had complete freedom to design the API however I wanted. No legacy endpoints to preserve. No backwards compatibility. That freedom is everything.
Day 1: API Contract First
Before writing a single migration, I designed the API contract. Every endpoint, every JSON shape, every relationship. Controllers don't care about your schema — your frontend cares about JSON shape. Get the JSON right first, then let the database serve it.
This took a day, not weeks. With AI-assisted development, you can iterate on contract design at conversation speed. Describe what you need, debate the trade-offs, and land on the right shape fast.
Days 2-3: Backend + Data Migration
Rails 8.1 made the backend fast to build. 32 models, 45 controllers, 62 routes, 3 real-time WebSocket channels. Order management, printer integration (sending PostScript to network printers via CUPS), real-time order status, admin-managed menus, and a full product modifier system for custom menu items.
But the real work was migrating 63K orders and 15K customers from one schema to another without losing a single transaction. The old schema was not normalized — redundant address fields, order totals that didn't match line items, missing timestamps.
I wrote idempotent migration scripts. Everything repeatable, pausable, rollbackable. Tested on a production copy multiple times before running it for real. This took longer than writing the models. But it worked.
Day 4: Mobile App
React Native with Expo and NativeWind. Product browsing with image galleries, customizable items, a cart with gift card wallet integration, real-time order tracking, push notifications, favorites, full order history. The API contract from Day 1 meant I wasn't guessing at data shapes — the mobile app just consumed what was already defined.
Day 5: Admin Panel + Polish
Vite + React 19 dashboard for staff. Product CRUD, pricing, printer configuration, staff accounts with role-based permissions, reporting dashboards, and real-time kitchen display screens. Then a pass across all three projects for responsive design, edge cases, and E2E tests.
The Patterns That Made This Possible
Here's what actually matters if you want to move at this speed:
Design the API contract before anything else
I cannot stress this enough. One day of contract design saved days of rework. When your frontend and backend teams (even if both "teams" are just you) agree on the JSON shape upfront, everything flows.
Use AI as a force multiplier, not a crutch
I used Claude Code for the entire build. Not to generate slop I'd have to rewrite — to think through architecture decisions, generate tested code that follows the patterns I'd already established, and move at a pace that would be physically impossible alone. The key is establishing patterns early and letting AI replicate them consistently.
Idempotency is non-negotiable
Every migration script, every seed, every state transition. Assume everything will run twice. This isn't just good practice — it's what lets you move fast without breaking things.
Real-time is a UX multiplier
ActionCable WebSocket channels meant customers see their order move from "confirmed" to "preparing" to "ready" live. No polling, no "refresh to check." Admins see kitchen status in real-time. It feels modern because it is.
Schema freedom is worth the rebuild
The old system's entity-attribute-value tables and copy-paste denormalization? Gone. Normalized, boring Rails models. Performance is better. Queries are faster. Reasoning about data is sane.
The hardest part is the data, not the code
Writing a kitchen display is a day. Migrating 15 years of customer data without losing a single order is the actual project.
By the Numbers
- 5 days, one developer
- 3 independent projects (Rails, React Native, React web) shipping together
- 700+ backend tests, 80+ E2E tests
- 3 real-time WebSocket channels
- ~63K orders migrated
- ~15K customers deduplicated and backfilled
- The restaurant kept taking orders the entire time
What's Left
Payment gateway integration, Apple/Android deep-linking credentials, app store submissions, and a website client. The bones are done — the hardest parts (API design, data migration, proving all three clients work together) are shipped.
The Point
A year ago, this project would have taken a team of four developers two to three months. Today, one developer with the right tools and the right approach can do it in under a week.
That's not a flex. That's a signal. The barrier to building production-quality software just dropped dramatically. If you've been sitting on a project because you thought you needed a team — you might not. Start with the API contract, pick tools that multiply your output, and build.
The tools are here. Go ship something.