Frontend Definition of Done — Ghasi Melmastoon
Status: draft (P0)
Owner: FE Platform + QA Guild
Applies to: every PR touching
apps/web-*,apps/mobile,apps/mobile-staff,apps/desktop-backoffice,apps/tablet-*,packages/ui-melmastoon,packages/feature-*,packages/i18n,packages/icons,packages/api-clients.
Every PR MUST satisfy every applicable box before merge. The PR template enforces this checklist.
Universal (every FE PR)
- Code reviewed and approved by at least one other engineer (and one designer if visual).
- Conventional commit messages (
feat,fix,refactor,docs,test,chore,perf,ci). -
tsc --noEmitpasses (strict mode, all flags). - ESLint passes — including
eslint-plugin-boundaries, the no-raw-color rule, no-physical-CSS rule, i18n-key existence check. - Prettier formatting clean.
- Unit + component tests green; coverage above floor (80% lines on
feature-*andui-melmastoon). - No
.only,.skip,debugger,console.logleft behind. - No new
TODO/FIXMEwithout a linked Jira ticket. - Secrets are not committed;
.env.exampleupdated if new env vars added. - PR description names the journey (J-NN) and surface(s) affected.
Design system + tokens
- Any new visual primitive is added to
packages/ui-melmastoon(not the app). - No raw hex colours in app code; uses semantic tokens (
bg-primary,text-on-surface). - No raw spacing values; uses spacing tokens (
p-3,gap-4). - Animations gated on
prefers-reduced-motion; durations + easings from motion tokens. - Storybook story added for any new primitive or significant variant; both LTR and RTL stories present.
- Visual regression: zero unreviewed Chromatic / Loki diffs (or explicit "accept" with justification).
Internationalisation
- All user-facing strings go through
next-intl(web/desktop) or@ghasi/i18n(mobile) — zero hardcoded English. - ICU MessageFormat used for plurals / gender / select.
- New locale keys exist in
enfirst; PR doesn't block on translations but lists the keys needing translation in the description. - Pseudo-locale (
en-XA) render checked; no truncation or clipping. - If RTL flow affected: tested in Pashto (
ps-AF); icons mirroring honoured per@ghasi/icons/manifest.json; logical CSS only. - Numerals: financial confirmations use Latin numerals (assertion in snapshot test).
Accessibility (WCAG 2.2 AA)
- axe-core runs with zero serious / critical issues on every changed Storybook story.
- Every interactive element reachable via keyboard in DOM order; visible focus ring (
--focus-ring). - Every icon-only button has an
aria-label(web) /accessibilityLabel(mobile). - Modal traps focus; closing returns focus to trigger.
- Route changes move focus to page heading on web.
- Touch targets >= 44x44 pt mobile, >= 32x32 px web.
- Form errors use
aria-describedby; error summary at top of form on submit. - Critical journeys re-tested with VoiceOver / TalkBack / NVDA per release.
Performance
- Web: Lighthouse-CI gate met — perf >= 90, a11y >= 95, best-practices >= 95, SEO >= 95 on changed routes.
- Web: bundle delta within budget (Initial JS <= 250 KiB gzipped per route; CSS <= 30 KiB).
- Mobile: Reassure benchmarks within budget for any changed hot screen; cold-start delta < 100 ms.
- Desktop: HK board / reservation list synthetic perf within budget; sync round-trip not regressed.
- No new layout shift on initial render (CLS p75 < 0.1).
- Lazy-loading + virtualisation for any list > 50 items.
- Images use
next/image(web) orexpo-image(mobile); blur LQIP for hero images.
Data / API
- All API access goes through the assigned BFF (
bff-consumer-service,bff-tenant-booking-service,bff-backoffice-service); no direct domain-service calls. - Generated OpenAPI types from
packages/api-clientsare used (no hand-typed request/response shapes). - React Query keys follow the convention in
docs/frontend/common/02-architecture-overview-frontend.md§4.1. - Mutations send
X-Idempotency-Key(ULID) and reuse it on retry. - PII never on telemetry surface; only minimal IDs in cookies/storage.
- Server-state queries declare
staleTime+gcTimemirroring BFF cache directives.
Forms + validation
- React Hook Form + shared Zod schemas (no bespoke validators).
- Same Zod schema reused on the BFF.
- Field-level + form-level error patterns from
docs/frontend/catalogs/C7-forms-and-validation-patterns.md(P1).
Theming / multi-tenancy
- Zero
if (tenantId === ...)branches in shared code. - Tenant-specific behaviour driven by
theme-config-serviceconfig (tokens, flow toggles, content blocks). - No raw
<a href>to a different tenant; alwaysPOST /handoff/{tenant}/{property}. - Suspended-tenant code path tested (platform-rendered "temporarily unavailable").
Security
- CSP unchanged or expanded explicitly with reviewer initials in PR body.
- No
dangerouslySetInnerHTMLwithout// security-reviewed:comment + reviewer initials. - Auth changes (token storage, biometric, DPoP) reviewed by Security Guild.
- Cookies set with correct
SameSite,Secure,HttpOnly. - Mobile: tokens in Keychain/Keystore; MMKV encrypted with key from secure store.
- No PII in logs / telemetry / Sentry breadcrumbs.
AI surfaces
- All provider calls go through
ai-gateway-service(no directopenai/anthropicimports in apps). -
AIProvenancerendered in every AI-generated artifact (model, prompt template id, decision id). - HITL: human accept/reject UI present;
decisionIdpropagated; no auto-apply on guest-facing state. - AI surface renders a fallback when local model unavailable (desktop) or rate-limited (web/mobile).
- Feature flag default-off, per-tenant opt-in.
- AI telemetry fields present (
ai.purpose,ai.model,ai.cost_usd,ai.safety.action).
Offline (where applicable)
- Web: PWA cache strategy unchanged or explicitly extended (service worker version bumped).
- Mobile: any new query type that should be available offline added to MMKV persister allow-list.
- Desktop: any new mutation goes through the outbox; conflict policy declared in
desktop/21-desktop-app-specification.md. - CTA disabled with offline banner where the action requires connectivity (no silent failure).
Telemetry / observability
-
@ghasi/telemetryused (no vendor SDKs). - New screens emit
view.page(web) /view.screen(mobile/desktop) on mount. - Multi-step flows emit
funnel.stepevents withstepandresult. - User-visible errors emit
error.surfacedwitherrorCode,httpStatus,path,traceId. - Web Vitals propagating to
web-vitals-> BFF telemetry endpoint (web). - Trace continuity:
traceparentpropagated across BFF -> domain calls; reflected back in client telemetry. - New telemetry events declared in
../frontend/catalogs/C1-telemetry-event-dictionary.md(P1).
Documentation
- If this PR changes behaviour that contradicts a spec doc, update the spec in the same PR.
- If this PR adds a new spec-worthy rule, add it to the relevant
docs/frontend/doc,docs/standards/, or.cursor/rules/. - If a new screen / surface ships, the corresponding
J-NNjourney file + per-platform spec are updated.
Bug fixes (in addition to above)
- A regression test is included in the same commit (unit, component, or e2e as appropriate).
- Root cause documented in the PR body, not just the symptom.
Before production deploy
- Canary / soft-launch percentage agreed with PM and SRE.
- Rollback plan verified.
- On-call alerted of deploy window.
- Feature flags set as intended; default-off for any new AI / payment / lock surface.
Spec wins
If this PR conflicts with docs/frontend/, the spec wins unless the PR also includes the spec update with explicit owner sign-off in the front matter (status: approved, approved-by: <name>).