
- Specimen
- QR Code 行動點餐共用核心
- Category
- Frontend Systems / Ordering Flow / Shared Architecture
- Location
- Taiwan
- Field Span
- 10 months to first launch, then 2.5 years of maintenance
- Collector
- Daco
- Role
- Sole Frontend Engineer / System Design / Integration
Project at a glance
A cloud ordering system serving multiple brands and settings. I worked across interaction flows, UI/UX, and frontend development to integrate dine-in, takeout, hospital delivery, set meals, multi-brand menus, and QR code parameters. The system has been used at Taoyuan Airport, the Taipei Veterans General Hospital food court, Nanmen Market, Matthew’s Choice, and POPEYES.
How I build systems
At Zhihui, I built and maintained a mobile ordering frontend system. Users entered through a QR code, and the URL carried parameters such as brand, store, and zone. The system then loaded the right store list, menu, payment methods, and service flow for that context.
The system was eventually deployed to Taoyuan Airport, the Taipei Veterans General Hospital food court, Nanmen Market, Matthew’s Choice, and POPEYES, with several more venues in testing. It was not a single-store interface. It had to support multiple brands, multiple venues, multiple payment flows, multiple languages, and different pickup rules.
The first live venue took about ten months to build. After launch, I continued maintaining the shared core and onboarding new venues for another two and a half years. What mattered here was not merely building ordering pages, but turning real-world business complexity into a reusable frontend system.
I was the only frontend engineer on the project. I handled the frontend architecture, API integration, combo logic, cart behavior, pricing, multilingual support, payment flows, order submission and retrieval, and the maintenance of the shared core itself. Since design often arrived only as static mockups, I also had to translate those screens into an actual operating system.
The hardest part of the system was not displaying menus. It was turning food-service rules into a flow where users would not make mistakes.
A combo meal could include required selections, min/max limits, add-ons, nested options, mutually exclusive conditions, brand-specific rules, and many price combinations. The API returned the full JSON rule set, but it did not validate each user interaction step for us. That logic had to live in the frontend.
I parsed the API rules layer by layer and embedded validation into each stage of interaction, instead of waiting until cart or checkout to announce that an order was invalid. My principle was simple: users should not have to understand the full rule system in order to place a legal order.
To avoid incomplete combos corrupting formal orders, I separated state into two layers: an in-progress editable item, and the final cart object. Only completed items could enter the cart. This allowed users to move back and forth through the flow without damaging already-added orders.
Pricing followed the same philosophy. Instead of incrementally adjusting totals, I recalculated prices from the full current state after every change. This prevented errors after repeated edits, backtracking, coupon use, add-ons, or brand-specific discounts.
Another critical task was converting frontend interaction state into a zero-tolerance API order format. The order JSON could reach more than twenty nested levels, and the API accepted almost no structural mistakes. Even absent customization fields often had to be present and explicitly set to null.
So I built a dedicated normalization layer that identified item types, restructured nested customization data, filled required fields, corrected value formats, removed frontend-only data, and generated the final standardized order JSON.
The frontend handled immediate interaction and live totals; the backend still retained final authority over pricing and order validity. After submission, the backend revalidated the order and returned an order number, and the frontend queried the confirmed order again before entering payment.
Although the same core was reused everywhere, different venues loaded different capabilities. Taoyuan Airport changed store lists and menus according to QR zone parameters. Other venues required delivery scheduling, internal hospital routing, or courier matching. Airport and Nanmen Market also supported multilingual behavior, with language preference saved to localStorage.
The system supported Apple Pay, Google Pay, LINE Pay, JKOPay, and counter payment. These were not one-call integrations. They required repeated data exchanges between frontend, backend, and payment services, making the frontend a coordinator of transactional state rather than a passive UI shell.
At the architecture level, I concentrated shared logic in a Git submodule: API integration, combo handling, cart behavior, live pricing, order formatting, order lookup, page management, multilingual handling, payment flow, and shared UI events and components.
When the shared core was updated, each venue only needed to update its submodule to receive the latest functionality. Once backend data and core parameters were ready, a new venue could produce a basic working version in roughly ten minutes. Only exceptional brand logic required additional frontend work.
This was one of the project’s most important outcomes: moving from one-off implementations toward a parameter-driven frontend system that could be rapidly reproduced.
Interestingly, the project was built with JavaScript and jQuery rather than React, because of team maintenance constraints. Even so, I still decomposed behavior in a component-like way and used .load() to dynamically bring in the required view modules. Layered content panels plus managed z-index let users move forward and back without reloading the entire page.
For testing, I often injected cart objects directly in Chrome DevTools or added temporary auto-run flows so the system could jump straight into a combo step, cart, checkout, payment, or order retrieval. That made it much faster to reproduce issues and validate price logic, JSON structure, and transaction flow.
If I rebuilt it today, I would use React, TypeScript, explicit state management, and automated tests. But I would still keep the same core principles: let API rules drive the UI, separate in-progress state from committed cart state, recalculate after every change, block invalid choices early, and centralize request normalization in one standard exit point.
