Munch · Franchise back office
Franchise Back Office
The unglamorous side of the product, where the actual operations happen.
- My role
- Feature development across the back office and the ordering app
- Stack
- Next.jsReact Server ComponentsTypeScriptTanStack Query
The problem
The customer-facing ordering app is what people see. Behind it sits the back office restaurant staff and franchisees actually work in every day — configuring stores, managing stock, pulling reports. It gets less design attention and carries more operational weight.
What I worked on
- Organisation overview and default order method pages — scaffolded from Figma with the API layer stubbed and typed ahead of the endpoints landing, so integration was a swap rather than a rewrite.
- Internal stock location transfers — moving inventory between locations within a site, with the state and validation that implies.
- Reporting surfaces — the consumers of the date range picker.
- An Alert component with auto-dismiss support, added to the shared library.
- State synchronisation debugging across React Server Components in the ordering app, where client and server state diverged in ways that only showed up on specific navigation paths.
An API design call worth mentioning
The stock-count-template/list endpoint returned templates without their stock location names — which meant rendering a list of 30 templates required 31 requests: one for the list, then one retrieve per row to resolve names.
That's a textbook N+1, and it wasn't going to pass review on our side. Rather than working around it on the client with a cache and hoping, I wrote up the problem for the backend team with the request count made concrete, and asked for { id, name } to be included in the list response directly.
I mention it because a chunk of frontend work is recognising when the right fix belongs on the other side of the API and making that case clearly, rather than absorbing the complexity into the client and calling it done.
Outcome
Operational surfaces that restaurant staff use daily, built to survive contact with real store configurations — and one list endpoint that no longer costs 31 requests to render.