QLess
Web DevelopmentCampus Pre-Order Web App
The QLess ordering flow started as a Figma prototype. This is what happened when it got built out as an actual web app: menu, cart, slot booking and OTP pickup, running in the browser with no framework and no backend to hide behind.
01
Problem
What problem were you solving?
A Figma prototype can hide a lot of assumptions: every screen looks reachable, every state looks handled, because someone drew it that way. The question was whether the pre-order flow designed in the QLess UX case study would hold up once it had to run on real state instead of pre-wired hotspots.
02
Solution
What did you build?
A deliberately tight-scope build, no server, no database, no login, just the core ordering loop a single-shop canteen needs, running entirely in the browser off nothing but JavaScript state and the DOM.
03
Key Features
Menu & cart
One shared state object drives every re-render.
Slot capacity
Pickup times can actually fill up and lock out.
OTP pickup
A real, live countdown, not a static screenshot.
Single-file app
View-switching via class toggles, no page reloads.
04
Architecture
How does it work?
A plain JS object keyed by item ID tracks quantities. Every add, remove or quantity change re-renders the menu list and cart bar from that single source of truth, no separate DOM state to fall out of sync.
05
Tech Stack & Tools
| Layer | Tools |
|---|---|
| Markup & styling | HTML5, CSS3 |
| Logic | Vanilla JavaScript, no framework |
| State | In-memory cart state, slot capacity model |
06
Technical Decisions
Why these technologies?
Why no framework?
A single cart object and a handful of render functions were enough to keep five views in sync, React would have added ceremony without solving a problem that existed.
Why cap slot capacity?
The zero-queue promise only means anything if slots can actually run out: an unlimited list of times would have made the demo hollow.
Why a real countdown?
A live timer, instead of a static screenshot of one, is what makes the collect-by-code pickup pattern feel true.
Why one HTML file?
Toggling a single active class between views keeps the whole flow, menu, cart, slots, OTP, running without a page reload breaking state.
07
Results
The design case study's "guaranteed pickup" promise only became a real engineering problem once slots needed actual capacity limits: a prototype can't run out of anything, an app has to decide what happens when it does.
08
Challenges
What difficulties did you face?
- Keeping five views in sync off one state object without a framework
- Modelling slot capacity so it fails gracefully once full
- Making a backend-free demo still feel like a real system
09
Limitations
What could be better
- No real backend, payment, or persistence across sessions
- Single-shop menu only, not multi-vendor
- State resets on page reload by design
10
What I Learned
- A working build finds what a mockup hides
- State management doesn't need a framework at this scale
- Constraints make a demo feel true
11
Future Improvements
- A real backend for persistence across sessions
- Multi-vendor menu support
- Actual payment integration in place of the simulated step