Design System & Guest Checkout at an E-Commerce Platform
A Vue + Quasar design system, guest checkout, and hardened auth flows.
Buyers were abandoning at a forced login before payment, and the frontend, originally built by backend developers, had no reusable component layer.
- role:
- First frontend developer: design system, checkout, auth; mentored junior developers
- stack:
- Vue 3 · Quasar · Pinia · Vitest · Cypress · GitHub Actions
- when:
- 2023–2025
- published:
Problem & constraints
I joined an e-commerce platform as its first dedicated frontend developer. Until then the frontend had been built by backend developers alongside their own work, without a reusable component layer to build from.
Two forces defined the work. First, the product needed a full design overhaul before its public release, with a UI designer whose Figma files were the contract; the designer had the last word on how things looked. Second, the product data was clear about where money was being lost: the product owner and a UX researcher found that many buyers reached a product page, clicked buy, got redirected to a login page, and never came back.
The team ran without a formal hierarchy: four backend developers working in Elixir, one developer covering both the database and DevOps, two Flutter developers on the mobile apps, and me on web. Each of us owned our domain and decided within it, aligned with the product owner; the big calls were made together with the CTO. What to build came from the CTO and the product and design side; my decisions were about how to build it on the web. My domain was the design overhaul, the component library, checkout, and authentication/authorization; later, mentoring two junior frontend developers as well.
The work came in stages. I did the overhaul alone in two weeks, from the homepage to every small menu page, and finished it for the public release. Smaller UI, UX and logic improvements followed as Jira issues from testers and the design side, and I started the component library alongside them, because the product still had none.
Architecture
Two client apps sit on the platform: the web app (Vue 3 with Quasar, Pinia for state, and the component library) and a Flutter mobile app for iOS and Android. The backend was mid-migration from a monolith to parallel Elixir microservices.
The new sign-in and purchase flow needed three pathways: registering an account, logging in to an existing one, and a guest checkout that asks only for what the purchase needs. The backend for registration was ready first, so the frontend work there was binding to it and getting the state management right. The backend for checkout was not ready, and it took another two to three months.
Checkout therefore ran client-side as a deliberate interim: the frontend built the cart, computed per-item and bundle discounts, called the payment provider directly, and received the result, because the backend could not yet serve live prices. Pinia stores carried the checkout state across steps, the auth sessions, and the admin-versus-user contexts, with role-based access checks in the router. Until the backend’s authorization was fully wired up, the frontend effectively was the access-control layer, so every step of every user story had to be walked for leaks and wrong-turn navigation. The decisions behind it are logged below, each with the alternative it beat.
Outcomes
The guest checkout measurably improved sales conversion: the abandonment point the UX research had identified was simply removed. The design system gave the team a shared component layer that cut the time to build features: around a hundred components, adopted by the entire team, matching the designer’s Figma while reusing Quasar underneath. Tests became trustworthy and mandatory per feature, and a GitHub Actions caching layer I added cut the app-packaging workflow, which ran on every merge, release, and test build, by roughly 40%.
The juniors I mentored moved from pair programming, through issue-driven guidance, to independently shipping better-shaped PRs with faster review cycles.
Lessons
I would have dropped Quasar at the first real inconvenience. The longer it stayed, the harder it became to let go, and bending its heavily-styled, class-laden components to match a designer’s bespoke system was a constant tax on exactly the work the design system was meant to make cheap. Wrapping a styled component framework under a pixel-contract design system means constantly fighting its opinions; if the designs are the contract, headless primitives (or your own) are the sounder foundation. It’s the clearest case of sunk-cost gravity I’ve worked through, and it changed how quickly I’m willing to re-litigate a foundation choice.
Key decisions
01 A design system wrapping Quasar
A bespoke layer of ~100 components wrapping and extending Quasar primitives.
The designer's Figma components simply didn't exist in Quasar, and the specs, not the framework's defaults, were the contract; the library could still reuse Quasar's logic and simple components underneath.
All of the roughly hundred components were adopted by the whole team. My honest hindsight on the “keep Quasar” half of this call is in Lessons above.
rejected: Using Quasar components directly in features
02 Guest checkout
A guest purchase flow, with email or phone required only to deliver the order.
The product owner's and UX researcher's data showed exactly where buyers vanished: at the forced login redirect between “buy” and payment.
rejected: Keeping registration as a precondition for buying
03 Client-side checkout as a deliberate interim
Computing cart totals and discount logic in the frontend, calling the payment provider directly.
The backend couldn't yet serve live prices, so client-side was the only way to ship correct per-item and bundle discount handling now, with server-side as the planned end state.
The tricky part was layered discounts: bundle-level discounts applying on top of per-item ones, against prices the backend only updated after the fact. The backend for server-side checkout was completed about two to three months later, and I then moved the frontend onto it.
rejected: Waiting for server-side checkout (live prices, inventory, payment sessions from the backend)
04 Frontend as the interim access-control layer
Ironclad, step-by-step RBAC checks in the Pinia stores and router guards.
Until the backend's authorization landed, the frontend was what stood between roles and data, so every user story had to be walked step by step for leaks and wrong-turn navigation.
rejected: Trusting backend enforcement that wasn't fully wired yet
05 Rebuilding trust in tests
Rewiring the test setup from scratch and gating every feature PR on tests.
The Vitest setup was so outdated that a failing test didn't mean anything was wrong; green had no signal, so trust had to be rebuilt from zero.
Vitest for units, Cypress for the many flows unit tests can't honestly cover. The gate applied to feature PRs only (hotfix, chore, and docs PRs were exempt), which is what made the policy stick.
rejected: Patching the existing suite incrementally
Key figures
| Metric | Value | Status |
|---|---|---|
| Design-system components | ~100 | reported |
Reported: Library size at handover