Skip to main content

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 --noEmit passes (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-* and ui-melmastoon).
  • No .only, .skip, debugger, console.log left behind.
  • No new TODO / FIXME without a linked Jira ticket.
  • Secrets are not committed; .env.example updated 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 en first; 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) or expo-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-clients are 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 + gcTime mirroring BFF cache directives.

Forms + validation

Theming / multi-tenancy

  • Zero if (tenantId === ...) branches in shared code.
  • Tenant-specific behaviour driven by theme-config-service config (tokens, flow toggles, content blocks).
  • No raw <a href> to a different tenant; always POST /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 dangerouslySetInnerHTML without // 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 direct openai / anthropic imports in apps).
  • AIProvenance rendered in every AI-generated artifact (model, prompt template id, decision id).
  • HITL: human accept/reject UI present; decisionId propagated; 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/telemetry used (no vendor SDKs).
  • New screens emit view.page (web) / view.screen (mobile/desktop) on mount.
  • Multi-step flows emit funnel.step events with step and result.
  • User-visible errors emit error.surfaced with errorCode, httpStatus, path, traceId.
  • Web Vitals propagating to web-vitals -> BFF telemetry endpoint (web).
  • Trace continuity: traceparent propagated 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-NN journey 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>).

References