Case Study · Custom Software · AI-Accelerated Delivery
Inside QueueMate, the free restaurant queue system First Mate designed, built, tested, and launched in days, not months, using an AI-accelerated, test-driven workflow.
First Mate Technologies · firstmate.tech · June 2026 · ~10 min read
Walk past the popular restaurants in any busy Philippine mall around 7 p.m. and you’ll see the same scene: a crowd bunched at the host stand, names on a paper list, no buzzers, and guests afraid to wander off in case they lose their place. Nobody hired us to fix this. We saw an everyday problem we knew we could solve well, so we built the solution ourselves. It’s QueueMate: a free, web-based queue that lets guests scan a QR code, join the line from their own phone, and roam the mall while a single host screen runs the whole floor. It’s live today at queuemate.tech.
This is the story of how we built it. And because QueueMate was our own idea, on our own initiative, it’s a fair test of how we work: no client brief to lean on, no one else to blame for the timeline. It is a working demonstration of how First Mate builds an MVP in days with AI, using AI coding agents inside a strict, test-driven engineering workflow, without trading away the security, privacy, and polish that production software demands. If you’re weighing who should build your next product, this is what to expect from a serious partner.
In a hurry? Jump to the results for the numbers, or talk to First Mate about building yours.
The challenge: a production-quality MVP, fast
QueueMate had to be a real product on day one, used by real guests during a real dinner rush, not a demo. That set a high bar across the board:
- Guests must be able to scan a QR code and join in under twenty seconds, on any phone, with nothing to install;
- Each guest needs an honest live position and wait estimate, holding their place even on flaky mall Wi-Fi;
- The host runs one calm screen: the waiting list and the table floor side by side, seating the next fitting party in one tap;
- There has to be a notification “your table is ready” moment that is impossible to miss across a noisy room;
- And it all has to respect Philippine Data Privacy Act (RA 10173) compliance baked in: consent at check-in, minimal data, and automatic deletion after the visit.
Built the traditional way, a scope like this (auth, a real-time multi-device data model, a host dashboard, a guest web app, SMS and email integrations, bilingual copy, accessibility, and a privacy-compliant data lifecycle) is a multi-month engagement. Founders stall exactly here: the idea is clear, but the months-long build (and its cost) is the wall. We wanted to knock that wall down.
Why traditional software is slow, and what changed
What “agentic coding” actually means
Agentic coding means AI agents that don’t just autocomplete a line. They navigate a real codebase, edit many files at once, run the test suite, read the failures, and verify their own changes against acceptance criteria. The output is real, ownable source code in your repository, reviewed by senior engineers. It is the difference between an intern who hands you a snippet and a teammate who opens a finished, tested pull request.
Agentic coding vs. “vibe coding” vs. no-code builders
This is not “vibe coding,” where you accept whatever the model emits and hope it holds. And it is not a no-code builder (Lovable, Bolt, Replit, and friends) that traps you inside a platform you can never fully own. Our agents work inside a professional engineering harness (TypeScript, a test suite, a human review gate, and architectural guardrails), so the speed of AI is paired with the discipline of a real software team. You get a codebase you own and can hand to any engineer.
Here is the practical difference:
| Traditional build | AI-accelerated build (First Mate) | |
|---|---|---|
| Timeline to MVP | 3 to 6+ months | Days to a few weeks |
| Iteration speed | Days per feature | Hours per feature |
| Code ownership | Yours | Yours. Real source, no lock-in |
| Quality gates | Often added late | Tests + human review on every change |
| Security & privacy | Frequently retrofitted | Designed in from the first commit |
Same destination, very different road. The AI-accelerated path only works with the guardrails in the right-hand column.
Why this matters for you. AI lets us write code fast. The test-first loop and the human review gate are what make that code safe to ship. Anyone can generate code in an afternoon; shipping production software in days is an engineering-process problem, and that process is exactly what you are hiring.
Our AI-accelerated development workflow
Speed came from the workflow, not from cutting corners. Every feature of QueueMate moved through the same loop, and no step is optional.
Specialized AI agents for each role
Rather than one generalist assistant, we run a team of specialized agents that mirror a real engineering org. Each milestone has a clear owner:
- Infra / DevOps agent handles scaffolding, CI/CD, environment and deploy on Vercel + Supabase.
- Backend engineer agent owns the data model, business logic, server actions, auth guards, and integrations.
- Frontend engineer agent builds the App Router pages, host dashboard, guest screens, and real-time UI.
- UI/UX designer agent shapes layout, empty/loading/error/ready states, and accessibility, all settled before any screen is built.
- QA test-case designer agent derives the test cases from the acceptance criteria, before code exists.
- Code-reviewer agent runs a mandatory, adversarial review gate on every diff.
A human architect directs the agents, makes the judgment calls, and owns the result. The agents do the heavy lifting; the engineer keeps the wheel.
The loop we never skip: RED → GREEN → REVIEW → VERIFY
- RED. Write the failing tests first. The acceptance criteria become executable tests before a single line of implementation exists. Run them; confirm they fail for the right reason.
- GREEN. Write the minimum code to make the tests pass, then run the whole suite green.
- REVIEW. A hard gate. The code-reviewer agent audits the diff against our architecture invariants. We work every finding until the review is clean. A feature is not “done” until the reviewer signs off.
- VERIFY. Drive the running app with Playwright (the same browser automation used to capture the screenshots in this article) and prove the acceptance criterion visibly holds. Committed end-to-end tests become the regression net.
“Done and green” means all of it: red tests existed first and now pass, the full unit and end-to-end suites are green, type-checking and linting are clean, the production build succeeds, the reviewer has signed off, and the feature is demonstrated against the live app. Anything less is not finished.

Figure B. The loop every QueueMate feature passed through. The REVIEW gate is where AI speed is kept honest.
Building QueueMate, step by step
The stack, and why we chose it
We chose a modern, type-safe stack that rewards fast iteration and is boring in all the right places:
- Next.js 16 (App Router, React 19) for server-rendered speed and Server Actions for every write.
- Supabase (Postgres + Realtime + Auth) so the database, live updates, and magic-link auth come from one place.
- Prisma owns the schema, migrations, and all business-logic reads and writes, fully type-safe end to end.
- TanStack Query on the client for an optimistic, self-healing cache.
- react-hook-form + zod pair into one schema that validates each form on the client and re-validates on the server, a single source of truth.
- shadcn/ui on Tailwind v4 for accessible, on-brand UI; next-intl for English + Filipino copy.
The result is the host dashboard below: the waiting list and the table floor on one screen, with the system already suggesting which party to seat at which table.

The live host dashboard. The queue (left) and the table board (right) update in real time; the app highlights the next party to seat and the best-fit table (“Seat next → T2”).
The live queue: real-time, server-authoritative, and private by design
The hardest part of a queue app is keeping every device honest and instant, without leaking personal data. Our rule: every change is a server action that writes to Postgres and then broadcasts a tiny, PII-free nudge to everyone watching that venue. The broadcast never carries names, mobiles, or emails: only opaque ids and statuses. Each guest’s phone hears “something changed” and re-reads only its own status through an unguessable token. We enforce the no-PII rule at the type level so it can’t be violated by accident:
export type VenueBroadcastPayload = {
kind: 'party' | 'table' | 'board' | 'reservation'
entityId?: string // opaque id only, never a name
status?: string // a status string, never PII
at?: number
}
// After every write, fire a best-effort, stateless broadcast.
// If it fails, the host's action still succeeds; subscribers
// self-heal on their next poll. A nudge is never the source of truth.
export async function broadcastVenueUpdate(
venueId: string,
payload: VenueBroadcastPayload,
): Promise<void> { /* POST to Supabase Realtime with the service-role key */ }From src/lib/realtime/broadcast.ts. The payload type is deliberately PII-free, enforcing a security invariant in the compiler.

Figure A. The real-time loop. The dashed path carries only ids and statuses; a guest’s real position and wait are fetched through their own private token, so no personal data is ever broadcast.
One queue, one source of truth: the matching engine
Who gets seated next is a question of fairness, and fairness is easy to get subtly wrong. We isolated the rule into a small, framework-free, exhaustively tested function: process the line first-come-first-served, give each party the tightest table that fits, and never let a small party at a big table block the person who has waited longest. It is pure logic (no database, no framework), which is exactly why it is so heavily test-driven:
// Greedy FCFS seating. Process parties oldest-first; for each,
// pick the tightest free table that fits and remove it from the
// pool. Parties with no fitting table keep waiting. This satisfies
// "first-come-first-served beats best-fit" and "never block the
// longest waiter".
export function suggestSeating(freeTables, waiting) {
const orderedParties = [...waiting].sort(compareByWait)
const available = [...freeTables]
const assignments = []
for (const party of orderedParties) {
let best = -1
for (let i = 0; i < available.length; i++) {
if (available[i].seatCount < party.partySize) continue
if (best === -1 || compareByFit(available[i], available[best]) < 0) best = i
}
if (best === -1) continue
assignments.push({ partyId: party.id, tableId: available[best].id })
available.splice(best, 1)
}
return assignments
}From src/lib/queue/matching.ts. The seating logic, abbreviated. Pure functions like this are the heaviest test-driven targets in the codebase.
Privacy by design, for Philippine law
Because QueueMate collects guest names, we treated RA 10173 as a first-class requirement, not a checkbox. Guests give freely-given consent at check-in, and our shared validation schema makes that consent literally impossible to bypass (an unticked box fails validation rather than slipping through). The same schema runs on the phone and on the server, so the rules can never drift apart:
export const guestJoinSchema = z
.object({
name: z.string().trim().min(1).max(80),
partySize: z.number().int().positive().max(50),
mobile: optionalMobile,
email: optionalEmail,
smsOptIn: z.boolean().default(false),
emailOptIn: z.boolean().default(false),
// RA 10173: consent must be explicitly TRUE; rejects false AND missing.
consent: z.literal(true),
})
.strict() // a client can't smuggle in server-minted fields
.superRefine((v, ctx) => {
if (v.smsOptIn && !v.mobile) ctx.addIssue({ path: ['mobile'], /* ... */ })
if (v.emailOptIn && !v.email) ctx.addIssue({ path: ['email'], /* ... */ })
})From src/lib/validation/guest.ts. One schema, used by both the guest form and the server action.
We collect the minimum: name and party size, plus a contact only if the guest opts in for an alert. A nightly job purges names, mobiles, and emails shortly after each visit ends, keeping only anonymized counts. The guest never types a single piece of personal data into a URL; their only credential is an unguessable token.
![]() | ![]() | ![]() |
| 1. Join in seconds, with clear consent | 2. A live place in line + honest wait | 3. An unmissable “table ready” alert |
The entire guest experience runs in a web link on the guest’s own phone: no app, no PII in the URL, bilingual EN/FIL.

Figure D. A party’s lifecycle. When the visit ends, an automated job purges the personal data.
Security in depth: ownership guards and database-level access control
Every venue-scoped action derives its venue on the server (it never trusts a client-supplied id), checks that the signed-in manager owns it, and only then writes. Underneath that, Postgres Row Level Security re-enforces the same ownership chain on every read, so even a bug in the application layer can’t expose another restaurant’s data. We also keep migration ownership clean: Prisma owns tables and indexes; Supabase SQL owns only the security policies.

Figure C. Defense in depth: an application-layer ownership guard plus a database-layer policy that traverses the same chain from the signed-in user down to every record.
The results: days, not months
| Days | from kickoff to a live, production app |
|---|---|
| 508 | automated tests, all green (466 unit + 42 end-to-end) |
| 9 | milestones shipped, M0 through M8 |
| < 2s | host taps “seat” → the guest’s screen updates |
| 0 | serious/critical accessibility issues across 8 screens (WCAG 2 AA) |
| 0 | pieces of personal data in any URL or broadcast |
QueueMate by the numbers.
What we shipped
The build moved through nine milestones, each gated by the same loop and the same review:
| M0 | Scaffolding, tooling, and CI/CD |
|---|---|
| M1 | Data model + pure-logic queue engine (matching, estimates, combining, purge) |
| M2 | Venue setup + manager authentication (magic link) + access control |
| M3 | Host dashboard: live queue + table board + quick-add |
| M4 | Fit-aware seating, mark-free, and table-combining |
| M5 | Guest QR join + live status page + real-time updates |
| M6 | “Table ready” notifications + SMS & email gateways |
| M7 | Privacy, consent, and the automated PII-purge job |
| M8 | Accessibility, performance, and responsive polish |
Reservations (host-logged call-in bookings that hold a table) were added afterward on the same engine.
Quality outcomes
Speed did not come at the cost of rigor. The review gate repeatedly earned its place. It caught an open-redirect vulnerability in the auth flow, a critical fail-open bug in the data-purge job (where a spoofable header could have bypassed the security check), and several transaction races in the table-combining logic. Each was fixed and locked down with a regression test before the milestone was allowed to close. That is the difference between code that demos and software that ships.
What this means if you need software built fast
Speed without sacrificing quality is no longer a trade-off
The old assumption was that you pick two of fast, cheap, and good. AI coding agents, wielded inside a disciplined engineering process, genuinely move that line. QueueMate is the proof: a secure, accessible, privacy-compliant, bilingual product, the kind of build that used to take a quarter, shipped in days, with the test suite and review trail to back it up.
How First Mate works with you
We bring this same AI-accelerated, test-driven approach to client work, whether you need an MVP off the ground, a fractional engineering team, or AI features built into an existing product. You get senior engineering judgment, a codebase you fully own, and a pace that lets you validate your idea in weeks instead of quarters.
Have an idea that needs building? First Mate designs and ships custom software that is fast and built to last. Tell us what you’re working on and we’ll show you what an AI-accelerated build looks like for your product. Book a call, or email hello@firstmate.tech.
Frequently asked questions
How long does it take to build an MVP with AI?
Weeks instead of the usual several months. For QueueMate, a working production app in days. The exact timeline depends on scope, but AI coding agents compress both the initial build and each round of iteration dramatically.
Is AI-generated code production-ready?
Only with the right guardrails. We pair AI agents with test-driven development, a mandatory human code-review gate, and end-to-end verification against the running app before anything ships. That process is what turns fast code into safe code.
What is agentic coding, and how is it different from no-code tools?
Agentic coding uses AI agents that navigate your codebase, edit many files, run tests, and verify their own changes, producing real, ownable source code. No-code builders lock you into a platform you can’t fully own or extend; agentic coding gives you a normal repository any engineer can pick up.
How much does it cost to build an MVP in the Philippines?
Offshore Philippine engineering already offers significant savings versus US rates, and AI acceleration further reduces the hours a build requires. The honest answer is that it depends on scope, so talk to us and we’ll give you a scoped estimate.
Can a software agency really move as fast as a solo AI builder?
Yes, and with senior architecture, security, and privacy built in. QueueMate’s PII-purge job, access-control layers, and accessibility work are exactly the things solo or no-code builds tend to skip, and they’re the things that matter once real users arrive.
What tech stack did you use for QueueMate?
Next.js (App Router) and React, Supabase (Postgres + Realtime + Auth), Prisma, TypeScript, and TanStack Query, chosen for real-time UX, end-to-end type safety, and fast iteration.
QueueMate is free for restaurants and live at queuemate.tech. It was designed and built by First Mate Technologies, a custom software studio that ships production products fast. If you’re building something, let’s talk.


