Files
slp-modular-cms/aidlc-docs/features/cms-frontend/construction/unit-1/nfr-design/nfr-design-patterns.md
T

3.0 KiB

NFR Design Patterns — Unit 1: Project Scaffold & Infrastructure

1. Performance — Route-Based Code Splitting (Answer Q1-A)

Pattern: Per-feature route modules with lazy-loaded layouts and page components.

  • TanStack Router createLazyFileRoute for dashboard, users, cms routes
  • Auth and root shell remain eager for fast initial paint and login
  • Vite automatically emits separate chunks per lazy route
  • Aligns with NFR-U1-01 (smallest possible bundle) and BR-U1-05 (TanStack Router)

2. Accessibility — Keyboard & Focus Trap (Answer Q2-A)

Pattern: Browser-native Tab order + shadcn/ui focus-visible + modal focus trap only.

  • All interactive elements use native <button>, <a>, form controls
  • focus-visible ring provided by shadcn/ui theme (Tailwind ring-2 ring-offset-2)
  • FocusTrap component (from @radix-ui/react-focus-trap or shadcn/ui dialog primitive) applied exclusively to modals and confirmation dialogs
  • No custom roving tabindex or arrow-key navigation unless explicitly required later

3. Testing — Feature-Scoped MSW Handlers (Answer Q3-B)

Pattern: Feature folders under src/mocks/ with barrel exports.

src/mocks/
  auth/
    handlers.ts
    fixtures.ts
  users/
    handlers.ts
  index.ts
  • auth/handlers.ts exports authHandlers array used in login, refresh, 401-retry tests
  • Easy to extend per future feature without central file bloat
  • Supports NFR-U1-04 (>70% coverage on auth components)

4. Internationalization — Lazy Language Loading (Answer Q4-B)

Pattern: Dynamic import of active locale only.

  • i18next initialized with react-i18next and i18next-browser-languagedetector
  • On language change: i18next.changeLanguage(lng) triggers import(../../public/locales/${lng}/translation.json)
  • Fallback to English; no eager bundling of both languages
  • Language switcher in user menu triggers the dynamic load + persists choice in localStorage via detector

5. Error Handling — Per-Component ProblemDetails Mapping (Answer Q5-B)

Pattern: Context-aware error presentation instead of global interceptor.

  • ApiClient throws typed ProblemDetailsError (extends Error)
  • Each page/form catches and decides:
    • 401/403 → redirect or global AuthContext logout
    • Validation errors (400) → inline field errors via react-hook-form
    • Transient errors → shadcn/ui toast via useToast()
  • Keeps UI responsive and avoids one-size-fits-all toasts

6. Configuration — Typed Vite Env + Optional Zod (Answer Q6-A)

Pattern: Strong typing in vite-env.d.ts + runtime validation hook.

// vite-env.d.ts
interface ImportMetaEnv {
  readonly VITE_API_BASE_URL: string;
  // future flags...
}
interface ImportMeta {
  readonly env: ImportMetaEnv;
}
  • Optional useAppConfig() hook runs Zod parse once at bootstrap (development warning only)
  • Production trusts .env values (no runtime overhead)

All patterns respect the "minimal viable" constraints from NFR Requirements (no Sentry, no pre-commit, basic a11y).