Skip to content

UX GUIDELINE

VietGara — Multi-Tenant SaaS Platform for Auto Garage Management & Maintenance

Version 2.0 (approved and implemented) — October 7, 2026 · Cloud: Google Cloud Platform (GCP) · Backend: Go

v2 replaces v1 (../v1/01_UX_Guideline.md) for all work (approved by the product owner on October 7, 2026; implemented in the web apps and the Flutter core package); the rationale is in 04_UI_Audit_and_Redesign_Proposal.md.

1. Introduction

1.1. Purpose

This document sets out the user experience (UX) principles for the VietGara platform, serving as the basis for the design team to build wireframes, user flows, and screen specifications in Figma, before moving on to the UI Design Spec (detailed per-screen specification) and the Design System (component library).

1.2. Design Tool and Source of Truth

The design system lives in code: the semantic tokens and components of vietgara-web-ui (web) and vietgara_core (Flutter), documented in 03_Design_System.md, with a runnable component gallery in the kit repo. Design work for a new screen is done in the gallery and in the apps themselves (light and dark, 360 / 768 / 1280px), reviewed in pull requests. Figma is optional: use it for exploration and stakeholder prototypes, and mirror the token file when a library is needed; it is never the source of truth.

  • 02_UI_Design_Spec.md — detailed specification for each screen
  • 03_Design_System.md — component library, color/typography tokens
  • Functional Requirements Document (FRD), Vision & Scope — source of business requirements

2. Core UX Principles

VietGara serves users with widely varying levels of technical proficiency — from garage owners/accountants comfortable at a computer, to technicians working in the shop with dirty hands or gloves, to end customers who only open the app for a few minutes at a time. The following 6 principles, based on Nielsen’s Usability Heuristics, are prioritized for VietGara’s real-world usage context:

PrincipleSpecific Application at VietGara
Clear visibility of system statusAlways show the status of quotes/repair orders/sync (especially important for the offline-capable Technician App)
Match real users’ language & mental modelUse familiar garage terminology (“Quote”, “Repair Order”), avoid technical jargon (“entity”, “record”)
User control & freedomAlways provide an escape route (cancel, go back) before irreversible actions (delete, close a repair order)
Consistency & standardsUse a single Design System (03_Design_System.md) across every screen — never invent a new pattern per feature
Error prevention over error handlingValidate input as it’s entered (e.g. phone numbers), disable the submit button when required fields are missing
Minimal interaction for mobile contextsThe Technician App is optimized for one-handed use, large buttons (at least 44x44pt), minimal typing, preferring selection/photo capture

3. User Personas

PersonaUsage ContextPrimary GoalPain Point
Garage Owner (Minh, 38)Desktop at the garage office, occasionally on phoneGet an overview of revenue, oversee staff across multiple garagesNo time to learn complex software; needs to see key numbers immediately upon opening the app
Garage Accountant (Hoa, 29)Desktop, focused work at end of day/monthAccurate settlement, error-free invoicingFears amount/tax errors; needs clear confirmation before issuing an invoice
Service Advisor (Tuan, 26)Desktop/tablet at the front desk, direct customer interactionCreate quotes quickly while the customer waitsNeeds fast interaction, doesn’t want to keep the customer waiting during data entry
Technician (Nam, 24)Phone, in the workshop, hands may be dirty/gloved, weak signalKnow exactly what to do, update progress quicklyDoesn’t want to type much; fears losing data if connectivity drops mid-task
Inventory Staff (Lan, 31)Desktop/tablet near the stock areaAccurate stock in/out, know when to reorderEasily confuses units/quantities if the interface isn’t clear
Supplier (Sang, 45; Phase 17 portal)Desktop or phone at the supplier’s sales desk; works from the garage’s purchase ordersConfirm what he can deliver and when, attach the delivery noteOrders arrive by phone or chat and get mixed up; wants one list of open orders per garage
Customer (Thao, 34)Personal phone, used for a few minutes at a time, infrequentlyKnow what stage the car is at, no surprise chargesUnfamiliar with auto-repair terminology; concerned about price transparency

4. Information Architecture

4.1. Owner Web (garage owners and staff)

flowchart TD
  auth["Sign in / Sign up<br/>e-mail + password or Google<br/>Forgot password (e-mail OTP)"] --> verify{"E-mail verified?"}
  verify -- no --> ve["Verify e-mail (6-digit OTP, 2 minutes)<br/>only Account is reachable meanwhile"]
  ve --> sel
  verify -- yes --> sel["Select active garage<br/>(owned or working in)"]
  sel --> dash[Dashboard]
  sel --> quotes["Quotes (1.2)"]
  sel --> ros["Repair Orders (1.3)"]
  sel --> inv["Inventory (1.3)"]
  sel --> cus["Customers & Vehicles, Suppliers"]
  sel --> bill["Billing & Receivables (1.4)"]
  sel --> rpt["Reports (1.5)"]
  sel --> staff["Staff: members, invitations"]
  sel --> gs["Garage settings: profile, hours, numbering, logo, status"]
  auth -.-> acct["Account: profile, language"]
  sel -.-> roles["Roles & groups (owners)"]
  sel -.-> sub["Subscription: plan, usage, change plan"]
  sel -.-> invs["My invitations"]

Menu entries are shown only when the member’s permissions in the active garage allow them (e.g. Customers needs customer.read); the server enforces the same rules.

4.1a. Admin Web (platform admins and admin staff)

A separate web app (vietgara-admin-web) with no garage context: sign in (no self-registration; the account must be listed as a platform admin) → Plans · Subscriptions · Payments (review queue, payment details and QR code, Release 5.2) · Account. Accounts that are not platform admins see an “Access denied” page that points them to the owner web.

flowchart TD
  auth["Sign in / Forgot password"] --> pa{"Platform admin?"}
  pa -- no --> deny["Access denied + Sign out"]
  pa -- yes --> plans["Plans"]
  pa -- yes --> subs["Subscriptions: search, extend"]
  pa -- yes --> pay["Payment requests: review, approve, reject; payment details"]
  pa -. yes .-> acct["Account: profile, language"]

From Phase 12 (Release 12.4) a Dashboard opens first after sign-in: new joiners and new licenses per day / month / year, conversions and active garages (FR-ADM-01..03).

4.1b. Owner App (Flutter, garage owners)

vietgara-owner-app is the mobile companion of the owner web for garage owners (Phase 2, Release 2.0). It covers what an owner checks or decides away from the counter. Setup and data entry stay on the web.

The bottom navigation has five tabs:

  • Dashboard
  • Quotes: send, record the decision, convert
  • Repairs: one tab per board column; line progress and technicians, close
  • Receivables: payments with vouchers, receipt PDF (the insurer split returns in Phase 17)
  • More: customers, vehicles, inventory, staff, subscription, invitations, user, language, sign out

The garage name in each app bar switches garage. A plan notice (trial, read-only, suspended) sits above the tabs.

4.1c. Admin App (Flutter, VietGara operators)

vietgara-admin-app is the mobile companion of the admin web (Phase 2, Release 2.1). It uses the same sign-in rule and access-denied screen as Section 4.1a, with Plans · Subscriptions (search, extend) · Payments (review queue and payment details, Release 5.2) · Account. The platform Dashboard is added in Release 12.4 and becomes the first screen.

4.2. Customer App

flowchart TD
  login["Login (phone OTP or Google)"] --> veh[My Vehicles]
  veh --> hist["Vehicle detail → repair history"]
  veh --> appr["Quotes awaiting approval → approve / reject"]
  veh --> prog[Real-time repair progress]
  veh --> pay["Payment → e-invoice"]

4.3. Technician App

flowchart TD
  login[Login] --> list["Today's repair orders (time-prioritized)"]
  list --> det["Order detail → update status per line item"]
  list --> photo[Take before/after photos]
  list --> sync["Sync indicator (online / offline / syncing)"]

5. Key User Flows

5.1. New Garage Onboarding

flowchart TD
  reg["Register: e-mail, password, name, optional phone<br/>(or Continue with Google)"] --> otp["Enter the 6-digit code e-mailed<br/>(valid 2 minutes, resend after 30 s)"]
  reg -. Google .-> welcome
  otp --> welcome["Garages page (empty state):<br/>create the first garage"]
  otp -. "also e-mailed (1.5)" .-> email["Registration-confirmation e-mail"]
  welcome --> garage["Create garage: name, address, phone, e-mail, tax ID"]
  garage --> invite["Suggest inviting staff (skippable):<br/>look up an existing user by e-mail or phone"]
  invite --> dash["Dashboard with trial banner (14 days)"]

5.2. Joining a Garage as Staff

flowchart TD
  e["Invitation e-mail<br/>'{owner} invites you to {garage}'"] --> signin["Sign in (the invitee already has a user)"]
  signin --> page["/invitations/:id — Accept or Decline"]
  page -- accept --> ws["Garage appears in the selector;<br/>menus follow the groups' permissions"]

5.3. Quote → Approval → Repair (multi-role touchpoints)

flowchart TD
  sa1["Service Advisor: create quote → choose Link or Manual → send"] --> mode{"Approval mode?"}
  mode -->|Link| c["Customer (link, e-mailed automatically if on file): view → approve/reject each line"]
  mode -->|Manual| sa1b["Service Advisor: asks the customer face to face → records the decision"]
  c --> sa2["Service Advisor: approval notification → convert to repair order → assign technician(s) per line"]
  sa1b --> sa2
  sa2 --> t["Technician (Owner Web Kanban board): update each line's progress → advisor closes once every line is completed"]

Design note: every hand-off between roles needs a proactive notification (push/SMS) — users should never have to check the app manually to find out something happened. In Manual mode there is no customer-facing touchpoint at all, by the owner’s own choice (FR-QUO-02) — the advisor’s own confirmation after recording the decision takes its place. The last step runs on the Owner Web Kanban board through Release 1.3 (FR-REP-03); the dedicated Technician App and before/after photos (FR-REP-04/05) are Phase 11.

5.4. Repair → Settlement → Collection (Release 1.4)

flowchart TD
  ro["Service Advisor closes the repair order"] --> acc["Garage Accountant: open the closed order → Create settlement (FR-BIL-01)"]
  acc --> coll["Record payment(s) as collected: amount, method (FR-BIL-03); the customer is the only payer (the insurer split returns in Phase 17)"]
  coll --> status["Status badge updates live: Pending → Partially paid → Paid"]
  status --> pdf["Export settlement receipt PDF (FR-DOC-01), handed or e-mailed to the customer"]

Design note: there is no separate Receivables screen — “Billing & Receivables” (Section 4.1) is the same settlement list, with an “outstanding only” filter serving FR-REC-01 (Database Design 6.1). A settlement is never created automatically when a repair order closes; the Accountant creates it deliberately from the closed order, the same direct-action pattern quote and repair order creation already use, so the amount is confirmed by a person before it becomes a bill.

6. Interaction Principles

  • Irreversible actions (deleting a customer, cancelling an invoice, closing a repair order) always show a confirmation dialog stating the consequence clearly — avoid vague wording (“Are you sure?” → replace with “Close this repair order? Line items cannot be edited after closing.”).
  • Long forms (e.g. creating a multi-item quote) are grouped logically, with auto-save drafts to prevent data loss on interruption.
  • Data tables (customer list, inventory) support filtering/sorting/search right at the top of the table, not hidden in a secondary menu.
  • Technician App: every data-writing action must work offline, with a consistent icon clearly showing “saved locally, pending sync” status.
  • Every action gives feedback near where it happened: success as a short toast (with Undo when reversible), errors beside the control or in place of the failed content; never only at the top of a long page.
  • Destructive confirmations name the object and the consequence (“Delete customer Nguyen Van A? Their 2 vehicles stay, but the link to this customer is removed.”); the most destructive ones (deactivating a garage, removing staff) require typing the name or an explicit second step.
  • Forms with unsaved changes warn before navigation (the Role editor’s behavior becomes the rule for every edit page); long forms keep their primary actions in a sticky bar.
  • Lists show their state honestly: skeleton while loading, an empty state with a next action on first use, “no results — clear filters” when filtering, and a retry on errors. Never an empty box.
  • Navigation gets out of the way when asked: the desktop sidebar collapses to an icon rail and peeks open on hover or keyboard focus (never hover-only), and remembers the user’s choice.
  • Dense by default: the web app is a work tool, so tables show 48px rows (40px compact) with numbers right-aligned; spacious layouts are reserved for sign-in, onboarding and the customer-facing quote page.
  • Power users get shortcuts (Ctrl/⌘ K command palette and garage switcher, / to focus search), but every shortcut has a visible equivalent.

7. Accessibility

Comply with at least WCAG 2.1 Level A for the main user flows (NFR-US-04): a minimum text/background contrast ratio of 4.5:1, a minimum tap target of 44x44pt on mobile, keyboard navigation support on Owner Web, and clear labels on every input field rather than relying on placeholder text alone.

Web (approved direction): raise the target to WCAG 2.2 Level AA for the main flows of vietgara-owner-web and vietgara-admin-web — 4.5:1 text contrast and 3:1 for control boundaries and focus indicators, a visible focus ring that is never obscured by sticky bars, pointer targets of at least 24px (44px on touch), dialogs that trap and restore focus, per-page document titles, a skip link, error summaries on forms, prefers-reduced-motion support and usability at 200% zoom. Enforced by token-contrast tests, axe checks in component tests and a manual keyboard pass per release. Details: 04_UI_Audit_and_Redesign_Proposal.md, Section 9. The mobile apps keep the existing target until reviewed separately.

8. Language & Tone (Content/UX Writing)

  • The interface is bilingual: Vietnamese (default) and English, switchable at any time from the header or the sign-in pages and saved on the user. Every string, error message and e-mail exists in both languages; no text is hard-coded in components.
  • Standard, friendly but professional Vietnamese — avoid being overly casual (no internet slang) and avoid overly stiff, bureaucratic phrasing.
  • Error messages always state the cause and how to fix it, never just “An error occurred”. The API returns stable error codes (API Specification, Section 1.2) that the interface translates, e.g. PLAN_LIMIT_REACHED → “Your plan’s limit is reached. Upgrade your plan.”
  • Action button labels use specific verbs (“Send Quote”, “Confirm Payment”) rather than generic ones (“OK”, “Continue”).

9. Working Method

9.1. Where the design lives

vietgara-docs/docs/02-Design/v2 -> principles, screen specs, tokens and component rules (these documents)
vietgara-web-ui -> web tokens, components and a gallery (`npm run dev`); token contrast test in CI
vietgara-flutter-core -> mobile theme, VgColors and shared widgets; theme contrast test in CI
vietgara-owner-web / admin-web -> web screens built only from the kit
vietgara-*-app -> mobile screens built from the core

9.2. Naming Convention

  • Components: PascalCase, named for the job (StatusBadge, PlateChip, Field); state and variant names follow 03_Design_System.md.
  • Tokens: semantic, never by hue (--muted-foreground, not --grey-500).
  • Screens: one page component per route, named for the screen (QuotesPage, QuoteFormPage).

9.3. Developer Handoff

  • A screen is “done” when it meets the Definition of Done in 03_Design_System.md section 10: all four states, both themes, three widths, keyboard pass, both languages.
  • Specs reference the numbered requirement (FR/NFR) and the section of 02_UI_Design_Spec.md; spacing, color and type are never annotated by hand because they come from the tokens.

9.4. Usability Testing

  • Run usability tests with at least 3-5 real users per role (especially technicians and customers) before finalizing the UI Design Spec for each major module, using the running staging build or a click-through prototype.