@react-spa-scaffold/mcp 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.md +423 -0
  2. package/dist/features/index.d.ts +5 -0
  3. package/dist/features/index.d.ts.map +1 -0
  4. package/dist/features/index.js +3 -0
  5. package/dist/features/index.js.map +1 -0
  6. package/dist/features/registry.d.ts +10 -0
  7. package/dist/features/registry.d.ts.map +1 -0
  8. package/dist/features/registry.js +508 -0
  9. package/dist/features/registry.js.map +1 -0
  10. package/dist/features/types.d.ts +45 -0
  11. package/dist/features/types.d.ts.map +1 -0
  12. package/dist/features/types.js +5 -0
  13. package/dist/features/types.js.map +1 -0
  14. package/dist/features/versions.d.ts +16 -0
  15. package/dist/features/versions.d.ts.map +1 -0
  16. package/dist/features/versions.js +46 -0
  17. package/dist/features/versions.js.map +1 -0
  18. package/dist/features/versions.json +5 -0
  19. package/dist/index.d.ts +22 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +43 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/resources/docs.d.ts +29 -0
  24. package/dist/resources/docs.d.ts.map +1 -0
  25. package/dist/resources/docs.js +105 -0
  26. package/dist/resources/docs.js.map +1 -0
  27. package/dist/resources/index.d.ts +2 -0
  28. package/dist/resources/index.d.ts.map +1 -0
  29. package/dist/resources/index.js +2 -0
  30. package/dist/resources/index.js.map +1 -0
  31. package/dist/server.d.ts +12 -0
  32. package/dist/server.d.ts.map +1 -0
  33. package/dist/server.js +115 -0
  34. package/dist/server.js.map +1 -0
  35. package/dist/tools/get-example.d.ts +51 -0
  36. package/dist/tools/get-example.d.ts.map +1 -0
  37. package/dist/tools/get-example.js +90 -0
  38. package/dist/tools/get-example.js.map +1 -0
  39. package/dist/tools/get-features.d.ts +30 -0
  40. package/dist/tools/get-features.d.ts.map +1 -0
  41. package/dist/tools/get-features.js +46 -0
  42. package/dist/tools/get-features.js.map +1 -0
  43. package/dist/tools/get-scaffold.d.ts +77 -0
  44. package/dist/tools/get-scaffold.d.ts.map +1 -0
  45. package/dist/tools/get-scaffold.js +153 -0
  46. package/dist/tools/get-scaffold.js.map +1 -0
  47. package/dist/tools/index.d.ts +4 -0
  48. package/dist/tools/index.d.ts.map +1 -0
  49. package/dist/tools/index.js +4 -0
  50. package/dist/tools/index.js.map +1 -0
  51. package/dist/utils/docs.d.ts +14 -0
  52. package/dist/utils/docs.d.ts.map +1 -0
  53. package/dist/utils/docs.js +64 -0
  54. package/dist/utils/docs.js.map +1 -0
  55. package/dist/utils/examples.d.ts +27 -0
  56. package/dist/utils/examples.d.ts.map +1 -0
  57. package/dist/utils/examples.js +399 -0
  58. package/dist/utils/examples.js.map +1 -0
  59. package/dist/utils/index.d.ts +5 -0
  60. package/dist/utils/index.d.ts.map +1 -0
  61. package/dist/utils/index.js +5 -0
  62. package/dist/utils/index.js.map +1 -0
  63. package/dist/utils/paths.d.ts +28 -0
  64. package/dist/utils/paths.d.ts.map +1 -0
  65. package/dist/utils/paths.js +40 -0
  66. package/dist/utils/paths.js.map +1 -0
  67. package/dist/utils/scaffold.d.ts +50 -0
  68. package/dist/utils/scaffold.d.ts.map +1 -0
  69. package/dist/utils/scaffold.js +500 -0
  70. package/dist/utils/scaffold.js.map +1 -0
  71. package/dist/version.d.ts +5 -0
  72. package/dist/version.d.ts.map +1 -0
  73. package/dist/version.js +19 -0
  74. package/dist/version.js.map +1 -0
  75. package/package.json +63 -0
  76. package/templates/.bundled +0 -0
  77. package/templates/CLAUDE.md +145 -0
  78. package/templates/docs/API_REFERENCE.md +58 -0
  79. package/templates/docs/ARCHITECTURE.md +185 -0
  80. package/templates/docs/CODING_STANDARDS.md +53 -0
  81. package/templates/docs/COMPONENT_GUIDELINES.md +301 -0
  82. package/templates/docs/E2E_TESTING.md +116 -0
  83. package/templates/docs/INTERNATIONALIZATION.md +67 -0
  84. package/templates/docs/TESTING.md +259 -0
  85. package/templates/docs/WORKFLOW.md +170 -0
  86. package/templates/src/App.tsx +42 -0
  87. package/templates/src/components/layout/Header.tsx +19 -0
  88. package/templates/src/components/layout/index.ts +1 -0
  89. package/templates/src/components/shared/ErrorBoundary/ErrorBoundary.tsx +104 -0
  90. package/templates/src/components/shared/ErrorBoundary/index.ts +1 -0
  91. package/templates/src/components/shared/LanguageSwitcher/LanguageSwitcher.tsx +45 -0
  92. package/templates/src/components/shared/LanguageSwitcher/index.ts +1 -0
  93. package/templates/src/components/shared/SEO/SEO.tsx +55 -0
  94. package/templates/src/components/shared/SEO/index.ts +1 -0
  95. package/templates/src/components/shared/ThemeToggle/ThemeToggle.tsx +41 -0
  96. package/templates/src/components/shared/ThemeToggle/index.ts +1 -0
  97. package/templates/src/components/shared/index.ts +4 -0
  98. package/templates/src/components/ui/button.tsx +48 -0
  99. package/templates/src/components/ui/dropdown-menu.tsx +228 -0
  100. package/templates/src/components/ui/form-error.tsx +95 -0
  101. package/templates/src/components/ui/loading.tsx +58 -0
  102. package/templates/src/components/ui/skeleton.tsx +52 -0
  103. package/templates/src/components/ui/sonner.tsx +34 -0
  104. package/templates/src/components/ui/spinner.tsx +40 -0
  105. package/templates/src/components/ui/visually-hidden.tsx +51 -0
  106. package/templates/src/contexts/mobileContext.tsx +66 -0
  107. package/templates/src/contexts/queryContext.tsx +28 -0
  108. package/templates/src/hooks/index.ts +7 -0
  109. package/templates/src/hooks/useContactForm.ts +33 -0
  110. package/templates/src/hooks/useExampleQuery.ts +20 -0
  111. package/templates/src/hooks/useLanguage.ts +23 -0
  112. package/templates/src/hooks/useMediaQuery.ts +53 -0
  113. package/templates/src/hooks/useThemeEffect.ts +31 -0
  114. package/templates/src/hooks/useTouchSizes.ts +16 -0
  115. package/templates/src/i18n/config.ts +11 -0
  116. package/templates/src/i18n/detectLanguage.ts +57 -0
  117. package/templates/src/i18n/index.ts +20 -0
  118. package/templates/src/i18n/loadCatalog.ts +30 -0
  119. package/templates/src/index.css +98 -0
  120. package/templates/src/lib/api.ts +142 -0
  121. package/templates/src/lib/config.ts +15 -0
  122. package/templates/src/lib/constants.ts +8 -0
  123. package/templates/src/lib/env.ts +53 -0
  124. package/templates/src/lib/format.ts +119 -0
  125. package/templates/src/lib/index.ts +24 -0
  126. package/templates/src/lib/routes.ts +11 -0
  127. package/templates/src/lib/storage.ts +91 -0
  128. package/templates/src/lib/storageKeys.ts +10 -0
  129. package/templates/src/lib/utils.ts +6 -0
  130. package/templates/src/lib/validations.ts +39 -0
  131. package/templates/src/locales/de.po +65 -0
  132. package/templates/src/locales/en.po +65 -0
  133. package/templates/src/locales/es.po +65 -0
  134. package/templates/src/main.tsx +107 -0
  135. package/templates/src/mocks/fixtures/index.ts +1 -0
  136. package/templates/src/mocks/fixtures/todos.ts +40 -0
  137. package/templates/src/mocks/handlers/index.ts +7 -0
  138. package/templates/src/mocks/handlers/todos.ts +59 -0
  139. package/templates/src/mocks/index.ts +3 -0
  140. package/templates/src/mocks/node.ts +9 -0
  141. package/templates/src/pages/Home.tsx +27 -0
  142. package/templates/src/pages/NotFound.tsx +28 -0
  143. package/templates/src/pages/index.ts +2 -0
  144. package/templates/src/stores/index.ts +2 -0
  145. package/templates/src/stores/preferencesStore.ts +85 -0
  146. package/templates/src/test/index.ts +8 -0
  147. package/templates/src/test/mocks.ts +17 -0
  148. package/templates/src/test/providers.tsx +54 -0
  149. package/templates/src/test-setup.ts +54 -0
  150. package/templates/src/types/api.ts +31 -0
  151. package/templates/src/types/index.ts +2 -0
  152. package/templates/src/types/preferences.ts +5 -0
  153. package/templates/src/vite-env.d.ts +10 -0
  154. package/templates/tests/unit/components/ErrorBoundary.test.tsx +193 -0
  155. package/templates/tests/unit/components/Header.test.tsx +33 -0
  156. package/templates/tests/unit/components/LanguageSwitcher.test.tsx +40 -0
  157. package/templates/tests/unit/components/Loading.test.tsx +76 -0
  158. package/templates/tests/unit/components/SEO.test.tsx +80 -0
  159. package/templates/tests/unit/components/ThemeToggle.test.tsx +62 -0
  160. package/templates/tests/unit/contexts/mobileContext.test.tsx +54 -0
  161. package/templates/tests/unit/hooks/useContactForm.test.ts +60 -0
  162. package/templates/tests/unit/hooks/useExampleQuery.test.tsx +94 -0
  163. package/templates/tests/unit/hooks/useLanguage.test.tsx +75 -0
  164. package/templates/tests/unit/hooks/useMediaQuery.test.ts +57 -0
  165. package/templates/tests/unit/hooks/useThemeEffect.test.ts +42 -0
  166. package/templates/tests/unit/i18n/detectLanguage.test.ts +40 -0
  167. package/templates/tests/unit/i18n/loadCatalog.test.ts +70 -0
  168. package/templates/tests/unit/lib/api.test.ts +142 -0
  169. package/templates/tests/unit/lib/format.test.ts +100 -0
  170. package/templates/tests/unit/lib/storage.test.ts +90 -0
  171. package/templates/tests/unit/lib/utils.test.ts +19 -0
  172. package/templates/tests/unit/lib/validations.test.ts +56 -0
  173. package/templates/tests/unit/stores/preferencesStore.test.ts +75 -0
@@ -0,0 +1,145 @@
1
+ # CLAUDE.md
2
+
3
+ AI assistant guidance for this React 19 + TypeScript + Vite 7 codebase. See [README.md](README.md) for project overview and tech rationale.
4
+
5
+ ## Commands
6
+
7
+ ```bash
8
+ npm run dev # Dev server at localhost:5173
9
+ npm run build # Production build (typecheck + bundle)
10
+ npm run typecheck # TypeScript only
11
+ npm run lint # ESLint check
12
+ npm run lint:fix # ESLint auto-fix
13
+ npm run format # Prettier format
14
+ npm run test # Vitest once
15
+ npm run test:watch # Vitest watch mode
16
+ npm run test:coverage # Coverage (80% threshold)
17
+ npm run e2e # Playwright E2E
18
+ npm run i18n:extract # Extract translations to .po
19
+ ```
20
+
21
+ ## Project Structure
22
+
23
+ See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for full structure and data flow.
24
+
25
+ ```
26
+ src/
27
+ ├── components/ # ui/ (primitives), layout/, shared/ (features)
28
+ ├── contexts/ # React Context providers
29
+ ├── hooks/ # Custom hooks
30
+ ├── lib/ # api, routes, config, utils, format, storage
31
+ ├── pages/ # Lazy-loaded route components
32
+ ├── stores/ # Zustand stores
33
+ └── types/ # TypeScript definitions
34
+
35
+ tests/unit/ # Vitest (mirrors src/)
36
+ e2e/ # Playwright tests
37
+ ```
38
+
39
+ ## Code Patterns
40
+
41
+ **Imports**: Always use `@/` path alias
42
+
43
+ **Components**: Named exports + `Props` interface. Pages use default exports for lazy loading.
44
+
45
+ **TypeScript**: `type` for unions, `interface` for objects
46
+
47
+ **State hierarchy**: Zustand (persisted) → TanStack Query (server) → Context (UI) → useState (local)
48
+
49
+ See [docs/CODING_STANDARDS.md](docs/CODING_STANDARDS.md) and [docs/COMPONENT_GUIDELINES.md](docs/COMPONENT_GUIDELINES.md).
50
+
51
+ ## UI Components (Shadcn/UI)
52
+
53
+ This project uses **Shadcn/UI** with radix-nova style. Components live in `src/components/ui/`.
54
+
55
+ ### Adding New Components
56
+
57
+ ```bash
58
+ npx shadcn@latest add button # Single component
59
+ npx shadcn@latest add dialog card input # Multiple components
60
+ ```
61
+
62
+ **Pattern**: Import directly (no barrel exports for UI):
63
+
64
+ ```tsx
65
+ import { Button } from '@/components/ui/button';
66
+ import { cn } from '@/lib/utils';
67
+ ```
68
+
69
+ ## MCP Servers (PREFER OVER WebSearch)
70
+
71
+ Use MCP servers for documentation lookup. They provide **structured, version-accurate data** directly from source—faster and more reliable than web scraping.
72
+
73
+ ### Why MCP over WebSearch?
74
+
75
+ - **Accuracy**: MCP fetches from official sources, not potentially outdated blog posts
76
+ - **Version-aware**: Gets docs for the exact library version you're using
77
+ - **Structured**: Returns code snippets, types, and examples in consistent format
78
+ - **Faster**: Direct API calls vs parsing HTML from search results
79
+
80
+ ### Shadcn MCP (UI Components)
81
+
82
+ | Need | Tool |
83
+ | ------------------- | ------------------------------------------------ |
84
+ | Find component | `mcp__shadcn__search_items_in_registries` |
85
+ | View component code | `mcp__shadcn__view_items_in_registries` |
86
+ | Usage examples | `mcp__shadcn__get_item_examples_from_registries` |
87
+ | CLI add command | `mcp__shadcn__get_add_command_for_items` |
88
+
89
+ ### Context7 MCP (All 3rd Party Libraries)
90
+
91
+ Use for **any npm package** documentation—not just React libraries:
92
+
93
+ ```
94
+ resolve-library-id → get-library-docs
95
+ ```
96
+
97
+ **Examples**:
98
+
99
+ - `react-hook-form` - Form validation patterns
100
+ - `@tanstack/react-query` - Query/mutation usage
101
+ - `zustand` - Store patterns
102
+ - `zod` - Schema validation
103
+ - `date-fns` - Date formatting
104
+ - `msw` - Mock service worker setup
105
+
106
+ ### Decision Flow
107
+
108
+ ```
109
+ Need UI component? → Shadcn MCP
110
+ Need library docs? → Context7 MCP (any npm package)
111
+ Need general info? → WebSearch (fallback only)
112
+ ```
113
+
114
+ ## Translations (CRITICAL)
115
+
116
+ All user-facing text MUST have translator comments. ESLint enforces this.
117
+
118
+ ```tsx
119
+ <Trans comment="Dashboard heading">Welcome back</Trans>;
120
+ t({ message: 'Close', comment: 'Close button' });
121
+ ```
122
+
123
+ See [docs/INTERNATIONALIZATION.md](docs/INTERNATIONALIZATION.md).
124
+
125
+ ## Testing
126
+
127
+ See [docs/TESTING.md](docs/TESTING.md) and [docs/E2E_TESTING.md](docs/E2E_TESTING.md).
128
+
129
+ Tests in `tests/unit/` mirror `src/` structure. 80% coverage required.
130
+
131
+ ```typescript
132
+ import { describe, it, expect, vi } from 'vitest';
133
+ import { screen, renderHook } from '@testing-library/react';
134
+ import { render, mockMatchMedia, server } from '@/test';
135
+ ```
136
+
137
+ MSW handlers auto-reset after each test.
138
+
139
+ ## Common Gotchas
140
+
141
+ 1. **Node.js >= 22.0.0** required (check `.nvmrc`)
142
+ 2. **Conventional commits** enforced by commitlint
143
+ 3. **Context hooks throw** outside provider (e.g., `useMobileContext()`)
144
+ 4. **Barrel exports** in each directory via `index.ts`
145
+ 5. **UI components** import directly: `@/components/ui/button` (no barrel)
@@ -0,0 +1,58 @@
1
+ # API Reference
2
+
3
+ Quick reference for what's available. For architectural decisions, see [Architecture Guide](./ARCHITECTURE.md).
4
+
5
+ ## Utilities (`lib/`)
6
+
7
+ | Module | Purpose | When to Use |
8
+ | ---------------- | --------------------- | ------------------------------------------------------------------- |
9
+ | `api.ts` | HTTP client | Any API calls - handles errors, timeouts, JSON. Includes API_CONFIG |
10
+ | `config.ts` | App configuration | Access APP_CONFIG, SENTRY_CONFIG |
11
+ | `env.ts` | Environment variables | Type-safe `env.VITE_*` access |
12
+ | `format.ts` | Formatters | Dates, numbers, currency, bytes - all locale-aware |
13
+ | `routes.ts` | Route constants | Type-safe navigation, avoid magic strings |
14
+ | `storage.ts` | localStorage wrapper | SSR-safe, typed storage with error handling |
15
+ | `storageKeys.ts` | Storage key constants | Centralized key management |
16
+ | `utils.ts` | Common utilities | `cn()` for Tailwind class merging |
17
+
18
+ ### Key Pattern: API Client
19
+
20
+ ```tsx
21
+ import { api } from '@/lib/api';
22
+
23
+ const data = await api.get<User[]>('/users');
24
+ // Throws ApiClientError on failure (check .status for HTTP code)
25
+ ```
26
+
27
+ ## Hooks (`hooks/`)
28
+
29
+ | Hook | Purpose | When to Use |
30
+ | ------------------------------ | --------------------- | ------------------------------------ |
31
+ | `useMediaQuery` | Track media query | Custom responsive logic |
32
+ | `useIsMobile` / `useIsDesktop` | Viewport checks | Conditional rendering by screen size |
33
+ | `useLanguage` | Locale state | Language switcher components |
34
+ | `useThemeEffect` | Theme sync | Apply theme to document |
35
+ | `useTouchSizes` | Touch-friendly sizing | Mobile-optimized UI |
36
+
37
+ ### Key Pattern: Context Hooks
38
+
39
+ Context hooks throw if used outside their provider:
40
+
41
+ ```tsx
42
+ const { isMobile } = useMobileContext();
43
+ // Throws if not wrapped in <MobileProvider>
44
+ ```
45
+
46
+ ## Contexts (`contexts/`)
47
+
48
+ | Context | Provider | Purpose |
49
+ | --------------- | ---------------- | ---------------------------------------- |
50
+ | `mobileContext` | `MobileProvider` | Viewport detection (isMobile, isDesktop) |
51
+
52
+ ## Stores (`stores/`)
53
+
54
+ | Store | Purpose | Persisted? |
55
+ | ------------------ | ------------------------------ | ------------------ |
56
+ | `preferencesStore` | User preferences (theme, etc.) | Yes (localStorage) |
57
+
58
+ Access via Zustand hooks - see store files for available actions.
@@ -0,0 +1,185 @@
1
+ # Architecture Guide
2
+
3
+ High-level architecture and key decisions. For API details, see [API Reference](./API_REFERENCE.md).
4
+
5
+ ## Tech Stack
6
+
7
+ | Layer | Technology | Why |
8
+ | -------------- | ------------------------ | ------------------------------------------- |
9
+ | Framework | React 19 + TypeScript | Largest ecosystem, concurrent features |
10
+ | Build | Vite 7 | 10-100x faster than Webpack, native ESM |
11
+ | Routing | React Router 7 | De facto standard, lazy loading support |
12
+ | Styling | Tailwind CSS 4 | No runtime cost, scales with team size |
13
+ | State | Zustand + TanStack Query | Minimal boilerplate, separation of concerns |
14
+ | Forms | React Hook Form + Zod | Minimal re-renders, type-safe validation |
15
+ | i18n | Lingui | Smaller runtime, compile-time extraction |
16
+ | Testing | Vitest + Playwright | Fast, Vite-native, true cross-browser |
17
+ | Error Tracking | Sentry | Industry standard, lazy-loaded |
18
+
19
+ ## Project Structure
20
+
21
+ ```
22
+ src/
23
+ ├── components/
24
+ │ ├── layout/ # Page structure (Header)
25
+ │ ├── shared/ # Feature components (ThemeToggle, LanguageSwitcher)
26
+ │ └── ui/ # Primitives (Button, Spinner) - shadcn/ui
27
+ ├── contexts/ # React Context providers
28
+ ├── hooks/ # Custom React hooks
29
+ ├── i18n/ # Internationalization setup
30
+ ├── lib/ # Utilities, API client, config, routes
31
+ ├── locales/ # Translation files (.po)
32
+ ├── mocks/ # MSW handlers and fixtures
33
+ ├── pages/ # Route page components
34
+ ├── stores/ # Zustand stores
35
+ ├── test/ # Test utilities and providers
36
+ └── types/ # Shared TypeScript definitions
37
+
38
+ tests/unit/ # Vitest tests (mirrors src/ structure)
39
+ e2e/ # Playwright end-to-end tests
40
+ ```
41
+
42
+ ### Why This Structure?
43
+
44
+ - **components/ui/**: Primitives from shadcn/ui. Direct imports (`@/components/ui/button`) because shadcn recommends against barrel exports for tree-shaking.
45
+ - **components/shared/**: Feature components with barrel exports. Each feature folder contains component + index.ts.
46
+ - **lib/**: Pure utilities with no React dependencies. Can be tested without rendering.
47
+ - **pages/**: One component per route. Default exports enable lazy loading.
48
+
49
+ ## Data Flow
50
+
51
+ ```
52
+ ┌─────────────────────────────────────────────────────────────┐
53
+ │ App Entry │
54
+ │ main.tsx → Providers → App.tsx → Routes → Pages │
55
+ └─────────────────────────────────────────────────────────────┘
56
+
57
+ ┌────────────────────┼────────────────────┐
58
+ ▼ ▼ ▼
59
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
60
+ │ Zustand │ │ TanStack │ │ Context │
61
+ │ Stores │ │ Query │ │ Providers│
62
+ └──────────┘ └──────────┘ └──────────┘
63
+ │ │ │
64
+ Persisted Server State UI State
65
+ Preferences (API Cache) (Mobile, etc)
66
+ ```
67
+
68
+ ## Key Architectural Decisions
69
+
70
+ ### 1. Provider Hierarchy
71
+
72
+ Providers wrap the app in this specific order:
73
+
74
+ ```tsx
75
+ <StrictMode>
76
+ <QueryProvider>
77
+ {' '}
78
+ {/* TanStack Query - outermost for global cache */}
79
+ <I18nProvider>
80
+ {' '}
81
+ {/* Lingui - translations available everywhere */}
82
+ <BrowserRouter>
83
+ {' '}
84
+ {/* React Router - routing context */}
85
+ <MobileProvider>
86
+ {' '}
87
+ {/* Viewport - depends on router for SSR */}
88
+ <ErrorBoundary>
89
+ <App />
90
+ <Toaster />
91
+ </ErrorBoundary>
92
+ </MobileProvider>
93
+ </BrowserRouter>
94
+ </I18nProvider>
95
+ </QueryProvider>
96
+ </StrictMode>
97
+ ```
98
+
99
+ **Why this order?**
100
+
101
+ - QueryProvider outermost so cache persists across route changes
102
+ - I18nProvider before Router so route components can use translations
103
+ - MobileProvider inside Router for potential SSR viewport detection
104
+ - ErrorBoundary innermost to catch errors in App without breaking providers
105
+
106
+ ### 2. State Management Separation
107
+
108
+ | Use Case | Solution | Location | Why |
109
+ | --------------------- | ------------------- | ----------------- | ----------------------------- |
110
+ | User preferences | Zustand + persist | `stores/` | Survives refresh, syncs tabs |
111
+ | Server/async data | TanStack Query | `hooks/use*Query` | Automatic caching, refetching |
112
+ | Shared UI state | React Context | `contexts/` | Prop drilling avoidance |
113
+ | Component-local state | useState/useReducer | Component file | Simplest solution |
114
+
115
+ **Key invariant**: Server state (TanStack Query) and client state (Zustand) never overlap. If data comes from an API, use Query. If it's user preference, use Zustand.
116
+
117
+ ### 3. Lazy Loading Strategy
118
+
119
+ Pages are lazy-loaded to reduce initial bundle size:
120
+
121
+ ```tsx
122
+ // App.tsx
123
+ const HomePage = lazy(() => import('@/pages/Home').then((m) => ({ default: m.HomePage })));
124
+
125
+ // Routes
126
+ <Suspense fallback={<PageSkeleton />}>
127
+ <Routes>
128
+ <Route path={ROUTES.HOME} element={<HomePage />} />
129
+ </Routes>
130
+ </Suspense>;
131
+ ```
132
+
133
+ **Why pages only?**
134
+
135
+ - Pages are the largest units and least likely to be needed immediately
136
+ - UI components are small and frequently reused—overhead of lazy loading outweighs benefit
137
+ - Shared components may be needed before Suspense resolves
138
+
139
+ ### 4. Error Handling Layers
140
+
141
+ | Layer | Mechanism | Catches |
142
+ | ---------- | -------------- | ----------------------- |
143
+ | Component | ErrorBoundary | React render errors |
144
+ | API | ApiClientError | Network/HTTP errors |
145
+ | Global | window.onerror | Uncaught exceptions |
146
+ | Production | Sentry | All errors with context |
147
+
148
+ **Key invariant**: Errors should never silently fail. Every error either:
149
+
150
+ - Shows user feedback (toast, error UI)
151
+ - Logs to console (development)
152
+ - Reports to Sentry (production)
153
+
154
+ ### 5. Translation Enforcement
155
+
156
+ All user-facing text must have translator comments. This is enforced by ESLint.
157
+
158
+ **Why mandatory comments?**
159
+
160
+ - Translators lack code context—"Close" could be adjective or verb
161
+ - Comments appear in PO files, reducing translation errors
162
+ - ESLint catches missing comments before merge
163
+
164
+ ## Import Conventions
165
+
166
+ ```tsx
167
+ // UI primitives: direct import (no barrel)
168
+ import { Button } from '@/components/ui/button';
169
+
170
+ // Shared components: barrel export
171
+ import { ThemeToggle } from '@/components/shared';
172
+
173
+ // Utilities
174
+ import { api } from '@/lib/api';
175
+ import { render } from '@/test';
176
+ ```
177
+
178
+ ## Related Docs
179
+
180
+ - [API Reference](./API_REFERENCE.md) - Utilities, hooks, and common patterns
181
+ - [Component Guidelines](./COMPONENT_GUIDELINES.md) - React component blueprint
182
+ - [Coding Standards](./CODING_STANDARDS.md) - TypeScript and state patterns
183
+ - [Testing](./TESTING.md) - Unit testing guidelines
184
+ - [E2E Testing](./E2E_TESTING.md) - Playwright patterns
185
+ - [Internationalization](./INTERNATIONALIZATION.md) - Lingui i18n setup
@@ -0,0 +1,53 @@
1
+ # Coding Standards
2
+
3
+ See [Architecture Guide](./ARCHITECTURE.md) for project structure and [Component Guidelines](./COMPONENT_GUIDELINES.md) for the complete React component blueprint.
4
+
5
+ ## TypeScript
6
+
7
+ Use `type` for unions, `interface` for object shapes:
8
+
9
+ ```tsx
10
+ type Theme = 'light' | 'dark' | 'system';
11
+
12
+ interface User {
13
+ id: string;
14
+ name: string;
15
+ }
16
+ ```
17
+
18
+ ## State Management
19
+
20
+ See [Architecture Guide](./ARCHITECTURE.md#state-management) for when to use each solution.
21
+
22
+ ### Query Hooks
23
+
24
+ Extract the fetcher function:
25
+
26
+ ```tsx
27
+ async function fetchTodos(): Promise<Todo[]> {
28
+ return api.get<Todo[]>('/todos');
29
+ }
30
+
31
+ export function useTodosQuery() {
32
+ return useQuery({
33
+ queryKey: ['todos'],
34
+ queryFn: fetchTodos,
35
+ });
36
+ }
37
+ ```
38
+
39
+ ### Context Hooks
40
+
41
+ Throw if used outside their provider:
42
+
43
+ ```tsx
44
+ const MyContext = createContext<MyValue | null>(null);
45
+
46
+ export function useMyContext() {
47
+ const context = useContext(MyContext);
48
+ if (!context) {
49
+ throw new Error('useMyContext must be used within MyProvider');
50
+ }
51
+ return context;
52
+ }
53
+ ```