@zigrivers/scaffold 3.6.0 → 3.8.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 (115) hide show
  1. package/README.md +127 -12
  2. package/content/knowledge/backend/backend-api-design.md +103 -0
  3. package/content/knowledge/backend/backend-architecture.md +100 -0
  4. package/content/knowledge/backend/backend-async-patterns.md +101 -0
  5. package/content/knowledge/backend/backend-auth-patterns.md +100 -0
  6. package/content/knowledge/backend/backend-conventions.md +105 -0
  7. package/content/knowledge/backend/backend-data-modeling.md +102 -0
  8. package/content/knowledge/backend/backend-deployment.md +100 -0
  9. package/content/knowledge/backend/backend-dev-environment.md +102 -0
  10. package/content/knowledge/backend/backend-observability.md +102 -0
  11. package/content/knowledge/backend/backend-project-structure.md +100 -0
  12. package/content/knowledge/backend/backend-requirements.md +103 -0
  13. package/content/knowledge/backend/backend-security.md +104 -0
  14. package/content/knowledge/backend/backend-testing.md +101 -0
  15. package/content/knowledge/backend/backend-worker-patterns.md +100 -0
  16. package/content/knowledge/cli/cli-architecture.md +101 -0
  17. package/content/knowledge/cli/cli-conventions.md +117 -0
  18. package/content/knowledge/cli/cli-dev-environment.md +121 -0
  19. package/content/knowledge/cli/cli-distribution-patterns.md +106 -0
  20. package/content/knowledge/cli/cli-interactivity-patterns.md +116 -0
  21. package/content/knowledge/cli/cli-output-patterns.md +107 -0
  22. package/content/knowledge/cli/cli-project-structure.md +124 -0
  23. package/content/knowledge/cli/cli-requirements.md +101 -0
  24. package/content/knowledge/cli/cli-shell-integration.md +130 -0
  25. package/content/knowledge/cli/cli-testing.md +134 -0
  26. package/content/knowledge/library/library-api-design.md +306 -0
  27. package/content/knowledge/library/library-architecture.md +247 -0
  28. package/content/knowledge/library/library-bundling.md +244 -0
  29. package/content/knowledge/library/library-conventions.md +229 -0
  30. package/content/knowledge/library/library-dev-environment.md +220 -0
  31. package/content/knowledge/library/library-documentation.md +300 -0
  32. package/content/knowledge/library/library-project-structure.md +237 -0
  33. package/content/knowledge/library/library-requirements.md +173 -0
  34. package/content/knowledge/library/library-security.md +257 -0
  35. package/content/knowledge/library/library-testing.md +319 -0
  36. package/content/knowledge/library/library-type-definitions.md +284 -0
  37. package/content/knowledge/library/library-versioning.md +300 -0
  38. package/content/knowledge/mobile-app/mobile-app-architecture.md +283 -0
  39. package/content/knowledge/mobile-app/mobile-app-conventions.md +180 -0
  40. package/content/knowledge/mobile-app/mobile-app-deployment.md +298 -0
  41. package/content/knowledge/mobile-app/mobile-app-dev-environment.md +257 -0
  42. package/content/knowledge/mobile-app/mobile-app-distribution.md +264 -0
  43. package/content/knowledge/mobile-app/mobile-app-observability.md +317 -0
  44. package/content/knowledge/mobile-app/mobile-app-offline-patterns.md +311 -0
  45. package/content/knowledge/mobile-app/mobile-app-project-structure.md +245 -0
  46. package/content/knowledge/mobile-app/mobile-app-push-notifications.md +321 -0
  47. package/content/knowledge/mobile-app/mobile-app-requirements.md +147 -0
  48. package/content/knowledge/mobile-app/mobile-app-security.md +338 -0
  49. package/content/knowledge/mobile-app/mobile-app-testing.md +400 -0
  50. package/content/knowledge/web-app/web-app-api-patterns.md +224 -0
  51. package/content/knowledge/web-app/web-app-architecture.md +116 -0
  52. package/content/knowledge/web-app/web-app-auth-patterns.md +256 -0
  53. package/content/knowledge/web-app/web-app-conventions.md +121 -0
  54. package/content/knowledge/web-app/web-app-data-patterns.md +218 -0
  55. package/content/knowledge/web-app/web-app-deployment-workflow.md +143 -0
  56. package/content/knowledge/web-app/web-app-deployment.md +134 -0
  57. package/content/knowledge/web-app/web-app-design-system.md +158 -0
  58. package/content/knowledge/web-app/web-app-dev-environment.md +173 -0
  59. package/content/knowledge/web-app/web-app-observability.md +221 -0
  60. package/content/knowledge/web-app/web-app-project-structure.md +160 -0
  61. package/content/knowledge/web-app/web-app-rendering-strategies.md +133 -0
  62. package/content/knowledge/web-app/web-app-requirements.md +112 -0
  63. package/content/knowledge/web-app/web-app-security.md +193 -0
  64. package/content/knowledge/web-app/web-app-session-patterns.md +214 -0
  65. package/content/knowledge/web-app/web-app-testing.md +249 -0
  66. package/content/knowledge/web-app/web-app-ux-patterns.md +162 -0
  67. package/content/methodology/backend-overlay.yml +73 -0
  68. package/content/methodology/cli-overlay.yml +69 -0
  69. package/content/methodology/library-overlay.yml +67 -0
  70. package/content/methodology/mobile-app-overlay.yml +71 -0
  71. package/content/methodology/web-app-overlay.yml +79 -0
  72. package/dist/cli/commands/init.d.ts +21 -0
  73. package/dist/cli/commands/init.d.ts.map +1 -1
  74. package/dist/cli/commands/init.js +261 -13
  75. package/dist/cli/commands/init.js.map +1 -1
  76. package/dist/cli/commands/init.test.js +206 -0
  77. package/dist/cli/commands/init.test.js.map +1 -1
  78. package/dist/config/schema.d.ts +1392 -64
  79. package/dist/config/schema.d.ts.map +1 -1
  80. package/dist/config/schema.js +82 -5
  81. package/dist/config/schema.js.map +1 -1
  82. package/dist/config/schema.test.js +302 -1
  83. package/dist/config/schema.test.js.map +1 -1
  84. package/dist/core/assembly/overlay-loader.d.ts.map +1 -1
  85. package/dist/core/assembly/overlay-loader.js +2 -1
  86. package/dist/core/assembly/overlay-loader.js.map +1 -1
  87. package/dist/core/assembly/overlay-loader.test.js +56 -0
  88. package/dist/core/assembly/overlay-loader.test.js.map +1 -1
  89. package/dist/e2e/game-pipeline.test.js +1 -0
  90. package/dist/e2e/game-pipeline.test.js.map +1 -1
  91. package/dist/e2e/project-type-overlays.test.d.ts +16 -0
  92. package/dist/e2e/project-type-overlays.test.d.ts.map +1 -0
  93. package/dist/e2e/project-type-overlays.test.js +834 -0
  94. package/dist/e2e/project-type-overlays.test.js.map +1 -0
  95. package/dist/types/config.d.ts +19 -2
  96. package/dist/types/config.d.ts.map +1 -1
  97. package/dist/types/index.d.ts +0 -1
  98. package/dist/types/index.d.ts.map +1 -1
  99. package/dist/types/index.js +0 -1
  100. package/dist/types/index.js.map +1 -1
  101. package/dist/wizard/questions.d.ts +27 -1
  102. package/dist/wizard/questions.d.ts.map +1 -1
  103. package/dist/wizard/questions.js +142 -3
  104. package/dist/wizard/questions.js.map +1 -1
  105. package/dist/wizard/questions.test.js +206 -8
  106. package/dist/wizard/questions.test.js.map +1 -1
  107. package/dist/wizard/wizard.d.ts +21 -0
  108. package/dist/wizard/wizard.d.ts.map +1 -1
  109. package/dist/wizard/wizard.js +27 -1
  110. package/dist/wizard/wizard.js.map +1 -1
  111. package/package.json +1 -1
  112. package/dist/types/wizard.d.ts +0 -14
  113. package/dist/types/wizard.d.ts.map +0 -1
  114. package/dist/types/wizard.js +0 -2
  115. package/dist/types/wizard.js.map +0 -1
@@ -0,0 +1,173 @@
1
+ ---
2
+ name: web-app-dev-environment
3
+ description: Dev server configuration, HMR setup, API proxy, environment variables, Docker for local services, and browser devtools for web app development
4
+ topics: [web-app, dev-environment, vite, webpack, hmr, docker, debugging]
5
+ ---
6
+
7
+ A fast, reliable local development environment is a force multiplier for the entire team. The goal is sub-second feedback loops for code changes and zero friction getting from a fresh checkout to a running app. Every minute spent fighting the dev environment is a minute not spent building the product.
8
+
9
+ ## Summary
10
+
11
+ A fast web app dev environment targets sub-second feedback loops with HMR and zero-friction onboarding. Use Vite for new projects (or the framework's built-in server for Next.js). Configure an API proxy to avoid CORS issues. Validate environment variables at startup with a schema. Run local dependencies in Docker Compose.
12
+
13
+ ## Deep Guidance
14
+
15
+ ### Dev Server Choice: Vite vs webpack
16
+
17
+ For new projects in 2024 and beyond, use **Vite** unless you have a specific reason not to:
18
+
19
+ - **Vite**: Native ESM dev server, near-instant startup regardless of project size, esbuild-powered transforms (10–100x faster than Babel), first-class support for React, Vue, Svelte, and TypeScript out of the box.
20
+ - **webpack (via Create React App, Next.js with webpack, or custom)**: Slower cold starts and HMR, but battle-tested and required by some frameworks. Next.js 13+ defaults to Turbopack (Rust-based, approaching Vite speed).
21
+
22
+ If you are on Next.js, you get the dev server bundled with the framework. Do not fight the framework's built-in tooling — configure it via `next.config.ts`, not by ejecting or customizing webpack directly unless absolutely necessary.
23
+
24
+ ### HMR Configuration
25
+
26
+ Hot Module Replacement keeps the page live-updating without full reloads. Ensure it is working correctly:
27
+
28
+ - With Vite: HMR works out of the box. If it stops working after upgrading, check `server.hmr` in `vite.config.ts`. Common issue: HMR fails silently when a module has a circular dependency.
29
+ - With React: Install `@vitejs/plugin-react` (uses Babel with Fast Refresh) or `@vitejs/plugin-react-swc` (uses SWC, 3–5x faster). Fast Refresh preserves component state on save — test that it works for your components.
30
+ - Watch for HMR performance degradation in large projects: if HMR is slow, profile with `vite --debug hmr`. The usual cause is a large shared module being invalidated on every change.
31
+
32
+ ### API Proxy Configuration
33
+
34
+ During development, your app's origin is `localhost:3000` but your API backend is `localhost:8000`. Avoid CORS issues and hardcoded localhost URLs by configuring a dev proxy:
35
+
36
+ ```typescript
37
+ // vite.config.ts
38
+ export default defineConfig({
39
+ server: {
40
+ proxy: {
41
+ "/api": {
42
+ target: "http://localhost:8000",
43
+ changeOrigin: true,
44
+ rewrite: (path) => path.replace(/^\/api/, ""),
45
+ },
46
+ },
47
+ },
48
+ });
49
+ ```
50
+
51
+ This means your frontend code always calls `/api/users` and the proxy handles routing to the backend. The same relative URL works in production when the API is behind the same domain. Never hardcode `http://localhost:8000` in application code.
52
+
53
+ ### Environment Variables
54
+
55
+ Use `.env` files for environment-specific configuration. Establish clear conventions:
56
+
57
+ - `.env.example` — committed, documents all variables with dummy values
58
+ - `.env.local` — gitignored, developer-specific overrides (actual API keys, local service URLs)
59
+ - `.env.development` — gitignored, shared dev defaults (can be committed if values are non-sensitive)
60
+ - `.env.production` — injected by CI/CD, never committed
61
+
62
+ Validate all required variables at startup. An app that silently uses `undefined` for a missing API URL is worse than one that crashes immediately with a clear error:
63
+
64
+ ```typescript
65
+ // lib/env.ts — validate at module load time
66
+ import { z } from "zod";
67
+
68
+ const envSchema = z.object({
69
+ VITE_API_URL: z.string().url(),
70
+ VITE_FEATURE_FLAGS: z.string().default(""),
71
+ });
72
+
73
+ export const env = envSchema.parse(import.meta.env);
74
+ ```
75
+
76
+ ### Docker for Local Services
77
+
78
+ Run local dependencies (databases, caches, queues, email servers) in Docker to keep developer machines clean and ensure consistency:
79
+
80
+ ```yaml
81
+ # docker-compose.yml
82
+ services:
83
+ postgres:
84
+ image: postgres:16-alpine
85
+ ports: ["5432:5432"]
86
+ environment:
87
+ POSTGRES_DB: myapp_dev
88
+ POSTGRES_USER: dev
89
+ POSTGRES_PASSWORD: dev
90
+ volumes:
91
+ - postgres_data:/var/lib/postgresql/data
92
+
93
+ redis:
94
+ image: redis:7-alpine
95
+ ports: ["6379:6379"]
96
+
97
+ mailpit:
98
+ image: axllent/mailpit
99
+ ports:
100
+ - "1025:1025" # SMTP
101
+ - "8025:8025" # Web UI
102
+
103
+ volumes:
104
+ postgres_data:
105
+ ```
106
+
107
+ Document the setup in the README: `docker compose up -d` starts all services. Never require developers to install PostgreSQL, Redis, or other services directly on their machines.
108
+
109
+ ### Getting to Zero-Friction Setup
110
+
111
+ Document the new developer setup flow and time it. Target under 10 minutes from fresh checkout to running app. Anything over 15 minutes will be skipped and developers will use workarounds.
112
+
113
+ Minimum `package.json` scripts:
114
+
115
+ ```json
116
+ {
117
+ "scripts": {
118
+ "dev": "vite",
119
+ "dev:full": "docker compose up -d && vite",
120
+ "build": "tsc && vite build",
121
+ "preview": "vite preview",
122
+ "test": "vitest",
123
+ "test:ui": "vitest --ui",
124
+ "lint": "eslint src --ext .ts,.tsx",
125
+ "typecheck": "tsc --noEmit"
126
+ }
127
+ }
128
+ ```
129
+
130
+ Include a `Makefile` or `justfile` for multi-step setup commands that developers run once (`make setup` installs deps, configures git hooks, copies `.env.example`).
131
+
132
+ ### Browser Devtools Configuration
133
+
134
+ Install and configure browser extensions that accelerate debugging:
135
+
136
+ - **React Developer Tools**: Component tree inspection, props/state browser, profiler for render performance.
137
+ - **Redux DevTools** (if using Redux): Action/state history, time-travel debugging.
138
+ - **Vite plugin for browser devtools**: Install `vite-plugin-inspect` to visualize the Vite plugin pipeline and module graph.
139
+
140
+ Configure source maps in development (`devtool: "eval-source-map"` in webpack or `sourcemap: true` in Vite) so stack traces point to TypeScript source, not compiled JavaScript. Without this, debugging is nearly impossible.
141
+
142
+ ### TypeScript Strict Mode
143
+
144
+ Enable strict mode from day one in `tsconfig.json`:
145
+
146
+ ```json
147
+ {
148
+ "compilerOptions": {
149
+ "strict": true,
150
+ "noUncheckedIndexedAccess": true,
151
+ "exactOptionalPropertyTypes": true
152
+ }
153
+ }
154
+ ```
155
+
156
+ Disabling strict mode to make TypeScript "less annoying" creates a false sense of safety. The errors strict mode surfaces are real bugs. Fix them instead of disabling the check.
157
+
158
+ ### VS Code Workspace Settings
159
+
160
+ Commit a `.vscode/settings.json` with recommended settings so all developers use consistent formatting:
161
+
162
+ ```json
163
+ {
164
+ "editor.formatOnSave": true,
165
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
166
+ "editor.codeActionsOnSave": {
167
+ "source.fixAll.eslint": true
168
+ },
169
+ "typescript.preferences.importModuleSpecifier": "non-relative"
170
+ }
171
+ ```
172
+
173
+ Commit `.vscode/extensions.json` with recommended extensions. Developers are prompted to install them on workspace open.
@@ -0,0 +1,221 @@
1
+ ---
2
+ name: web-app-observability
3
+ description: Real User Monitoring, Core Web Vitals tracking, error tracking with Sentry, CDN analytics, custom performance marks, and performance regression alerting
4
+ topics: [web-app, observability, rum, core-web-vitals, sentry, performance, monitoring]
5
+ ---
6
+
7
+ You cannot improve what you cannot measure. Frontend observability is often treated as an afterthought — added after users start complaining — but by then you have no baseline to regress against and no historical data to understand when performance degraded or errors started. Real User Monitoring (RUM) captures the experience of your actual users on their actual devices and networks, which lab-based tests like Lighthouse cannot replicate. Core Web Vitals are Google's standardized metrics for page experience and directly influence search ranking.
8
+
9
+ ## Summary
10
+
11
+ ### Real User Monitoring (RUM)
12
+
13
+ RUM collects performance and behavioral data from real user sessions in production. Unlike synthetic monitoring (scheduled tests from a data center), RUM reflects the diversity of real-world conditions: slow Android devices, congested mobile networks, aggressive ad blockers, and geographically distant users.
14
+
15
+ **Key RUM metrics:**
16
+
17
+ - **Core Web Vitals** — Google's page experience signals (see below)
18
+ - **Time to First Byte (TTFB)** — server response latency
19
+ - **First Contentful Paint (FCP)** — when the first content is painted
20
+ - **Time to Interactive (TTI)** — when the page is reliably interactive
21
+ - **Custom marks** — application-specific milestones (e.g., "dashboard data loaded")
22
+ - **Error rate** — JavaScript exceptions per session
23
+ - **Rage clicks** — repeated clicks on non-interactive elements (UX frustration signal)
24
+ - **Dead clicks** — clicks on elements that produce no response
25
+
26
+ **RUM tools:** Vercel Analytics, Datadog RUM, New Relic Browser, Sentry Performance, web-vitals library (self-hosted reporting).
27
+
28
+ ### Core Web Vitals
29
+
30
+ Google's three Core Web Vitals measure loading, interactivity, and visual stability:
31
+
32
+ | Metric | Measures | Good | Needs Improvement | Poor |
33
+ |---|---|---|---|---|
34
+ | **LCP** (Largest Contentful Paint) | Load performance | ≤ 2.5s | 2.5–4s | > 4s |
35
+ | **INP** (Interaction to Next Paint) | Responsiveness | ≤ 200ms | 200–500ms | > 500ms |
36
+ | **CLS** (Cumulative Layout Shift) | Visual stability | ≤ 0.1 | 0.1–0.25 | > 0.25 |
37
+
38
+ **Common LCP causes and fixes:**
39
+ - Unoptimized hero images → use `srcset`, WebP/AVIF, CDN, `loading="eager"`, `fetchpriority="high"`
40
+ - Render-blocking CSS/fonts → inline critical CSS, use `font-display: swap`
41
+ - Slow TTFB → edge caching, CDN, server-side optimization
42
+
43
+ **Common CLS causes and fixes:**
44
+ - Images without explicit `width`/`height` attributes → always set dimensions
45
+ - Late-loading ads or embeds → reserve space with aspect-ratio boxes
46
+ - Custom fonts causing text reflow → use `font-display: optional` or `size-adjust`
47
+ - Dynamic content injected above viewport content → append below, not prepend above
48
+
49
+ **INP (replaced FID in 2024):** Measures the responsiveness of all user interactions, not just the first. Long JavaScript tasks (>50ms) block the main thread and inflate INP. Use `scheduler.postTask()`, web workers, and code splitting to break up long tasks.
50
+
51
+ ### Error Tracking with Sentry
52
+
53
+ Sentry captures JavaScript exceptions, stack traces, user context, and breadcrumbs (the sequence of events leading to the error). Configure it to filter noise and surface actionable errors.
54
+
55
+ **Critical Sentry configuration:**
56
+ - Source maps for readable stack traces (never ship source maps publicly — upload to Sentry only)
57
+ - User context (attach user ID, plan tier — never PII like email without consent)
58
+ - Release tracking to correlate error spikes with deployments
59
+ - Sampling rate: 100% for errors, 10–20% for performance transactions in high-traffic apps
60
+
61
+ ### Performance Regression Alerting
62
+
63
+ The goal is to catch regressions before they reach users or before they compound. Alert on:
64
+ - LCP p75 (75th percentile) increases by more than 300ms from the rolling 7-day average
65
+ - Error rate increases by more than 0.5% from the rolling 24-hour baseline
66
+ - Any new error type appearing in production for the first time
67
+
68
+ ## Deep Guidance
69
+
70
+ ### Web Vitals Collection
71
+
72
+ ```typescript
73
+ // web-vitals library — collect and report Core Web Vitals
74
+ import { onLCP, onINP, onCLS, onFCP, onTTFB } from 'web-vitals';
75
+
76
+ function sendToAnalytics(metric: any) {
77
+ // Batch metrics to avoid sending too many beacons
78
+ const body = JSON.stringify({
79
+ name: metric.name,
80
+ value: metric.value,
81
+ rating: metric.rating, // 'good', 'needs-improvement', 'poor'
82
+ id: metric.id,
83
+ navigationType: metric.navigationType,
84
+ url: window.location.pathname,
85
+ // Attach context for segmentation
86
+ connectionType: (navigator as any).connection?.effectiveType,
87
+ deviceMemory: (navigator as any).deviceMemory,
88
+ });
89
+
90
+ // sendBeacon is non-blocking and survives page unload
91
+ if (navigator.sendBeacon) {
92
+ navigator.sendBeacon('/api/vitals', body);
93
+ } else {
94
+ fetch('/api/vitals', { method: 'POST', body, keepalive: true });
95
+ }
96
+ }
97
+
98
+ // Register all Core Web Vitals + FCP + TTFB
99
+ onLCP(sendToAnalytics);
100
+ onINP(sendToAnalytics);
101
+ onCLS(sendToAnalytics);
102
+ onFCP(sendToAnalytics);
103
+ onTTFB(sendToAnalytics);
104
+ ```
105
+
106
+ Always use `navigator.sendBeacon` for analytics reporting — it queues the request to be sent after the page unloads without blocking navigation.
107
+
108
+ ### Custom Performance Marks
109
+
110
+ Use the User Timing API to measure application-specific milestones that browser APIs cannot capture:
111
+
112
+ ```typescript
113
+ // Mark application-level performance milestones
114
+ class PerformanceTracker {
115
+ private marks: Map<string, number> = new Map();
116
+
117
+ mark(name: string): void {
118
+ performance.mark(name);
119
+ this.marks.set(name, performance.now());
120
+ }
121
+
122
+ measure(name: string, startMark: string, endMark?: string): number {
123
+ const end = endMark || name + '-end';
124
+ if (!endMark) this.mark(end);
125
+
126
+ const measure = performance.measure(name, startMark, end);
127
+ const duration = measure.duration;
128
+
129
+ // Report to RUM
130
+ this.report({ name, duration });
131
+ return duration;
132
+ }
133
+
134
+ private report(metric: { name: string; duration: number }): void {
135
+ navigator.sendBeacon?.('/api/perf', JSON.stringify(metric));
136
+ }
137
+ }
138
+
139
+ const perf = new PerformanceTracker();
140
+
141
+ // Usage in application code
142
+ async function loadDashboard() {
143
+ perf.mark('dashboard-fetch-start');
144
+ const data = await fetchDashboardData();
145
+ perf.mark('dashboard-fetch-end');
146
+
147
+ perf.measure('dashboard-fetch', 'dashboard-fetch-start', 'dashboard-fetch-end');
148
+
149
+ perf.mark('dashboard-render-start');
150
+ renderDashboard(data);
151
+ perf.mark('dashboard-render-end');
152
+
153
+ perf.measure('dashboard-render', 'dashboard-render-start', 'dashboard-render-end');
154
+ }
155
+ ```
156
+
157
+ These custom marks appear in Chrome DevTools Performance panel and can be reported to your RUM backend for tracking.
158
+
159
+ ### Sentry Setup for Next.js
160
+
161
+ ```typescript
162
+ // sentry.client.config.ts
163
+ import * as Sentry from '@sentry/nextjs';
164
+
165
+ Sentry.init({
166
+ dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
167
+ environment: process.env.NEXT_PUBLIC_ENV,
168
+
169
+ // Performance monitoring sample rate — adjust based on traffic volume
170
+ tracesSampleRate: process.env.NODE_ENV === 'production' ? 0.1 : 1.0,
171
+
172
+ // Replay for error sessions only (privacy-conscious default)
173
+ replaysOnErrorSampleRate: 1.0,
174
+ replaysSessionSampleRate: 0.0,
175
+
176
+ // Filter noise — don't track network errors from ad blockers
177
+ ignoreErrors: [
178
+ 'ResizeObserver loop limit exceeded',
179
+ 'Non-Error promise rejection captured',
180
+ /Loading chunk \d+ failed/,
181
+ ],
182
+
183
+ beforeSend(event, hint) {
184
+ // Strip PII from error context
185
+ if (event.user) {
186
+ delete event.user.email;
187
+ delete event.user.username;
188
+ }
189
+ return event;
190
+ },
191
+
192
+ integrations: [
193
+ Sentry.replayIntegration({
194
+ maskAllText: true, // Privacy: mask all text in replays
195
+ blockAllMedia: true, // Privacy: block media in replays
196
+ }),
197
+ ],
198
+ });
199
+ ```
200
+
201
+ ### CDN Analytics and Cache Hit Rate
202
+
203
+ Monitor CDN cache performance as a leading indicator for LCP and TTFB:
204
+
205
+ - **Cache hit rate** — percentage of requests served from CDN cache vs origin. Target >90% for static assets, >70% for edge-cached HTML.
206
+ - **Origin shield hit rate** — for CDN tiers that include an origin shield, a low rate indicates cold cache or poor cache-control headers.
207
+ - **Edge latency by region** — identify geographic regions where users have poor performance; expand CDN PoP coverage or investigate origin latency.
208
+
209
+ Key cache-control headers:
210
+ ```
211
+ # Immutable static assets (hashed filenames)
212
+ Cache-Control: public, max-age=31536000, immutable
213
+
214
+ # HTML pages — revalidate frequently but serve stale while revalidating
215
+ Cache-Control: public, max-age=0, s-maxage=86400, stale-while-revalidate=3600
216
+
217
+ # API responses — no public cache, short browser cache
218
+ Cache-Control: private, max-age=30
219
+ ```
220
+
221
+ Set `Surrogate-Key` (Fastly) or `Cache-Tag` (Cloudflare) headers on HTML responses to enable targeted cache purging when content changes.
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: web-app-project-structure
3
+ description: Directory layout conventions, route organization, shared vs feature modules, barrel exports, and config file placement for web apps
4
+ topics: [web-app, project-structure, architecture, routing, modules]
5
+ ---
6
+
7
+ A well-structured web app project is navigable by any developer without a tour. The directory layout should communicate the architecture at a glance: where pages live, where shared code lives, where API logic lives, and where configuration lives. A poor structure forces every developer to ask "where does this go?" on every new file they create.
8
+
9
+ ## Summary
10
+
11
+ Web app project structure separates `app/` (routes and layouts), `features/` (domain-owned modules), `components/` (shared UI), `hooks/` (shared hooks), and `lib/` (framework-agnostic utilities). Routes mirror URL structure with thin page files. Feature modules own their components, hooks, and types; shared modules have zero imports from feature modules.
12
+
13
+ ## Deep Guidance
14
+
15
+ ### Standard Directory Layout
16
+
17
+ For a Next.js or similar SSR framework, the canonical structure is:
18
+
19
+ ```
20
+ src/
21
+ app/ # App Router pages and layouts (Next.js 13+)
22
+ pages/ # Pages Router (Next.js legacy; or Remix/Vite routes)
23
+ components/ # Shared, reusable UI components
24
+ features/ # Feature modules (colocated components + hooks + logic)
25
+ hooks/ # Shared custom hooks used across features
26
+ lib/ # Framework-agnostic utilities and service clients
27
+ api/ # API route handlers (serverless functions)
28
+ types/ # Shared TypeScript types and interfaces
29
+ styles/ # Global CSS, design tokens, theme config
30
+ public/ # Static assets served at root (images, fonts, robots.txt)
31
+ ```
32
+
33
+ For a Vite/React SPA, drop `app/` and `api/` and substitute:
34
+
35
+ ```
36
+ src/
37
+ routes/ # Route components and nested layouts
38
+ pages/ # Page-level components (one per route)
39
+ ```
40
+
41
+ ### Route Organization
42
+
43
+ Routes should mirror the URL structure. Avoid flat route files that make the hierarchy ambiguous:
44
+
45
+ - `/dashboard` → `app/dashboard/page.tsx`
46
+ - `/dashboard/settings` → `app/dashboard/settings/page.tsx`
47
+ - `/users/[id]` → `app/users/[id]/page.tsx`
48
+
49
+ Keep route files thin — they orchestrate data loading and pass props to feature components. Business logic belongs in `features/`, not in the page file.
50
+
51
+ **Layouts**: Use layout files (`layout.tsx`) to share navigation, auth checks, and providers across route groups. Do not repeat these in every page file.
52
+
53
+ ### Shared vs Feature Modules
54
+
55
+ The critical distinction is "who owns this code":
56
+
57
+ - **Feature module** (`features/checkout/`): Owned by one product domain. Contains everything the checkout feature needs — components, hooks, API calls, types. Other features do not import from it directly; they use shared interfaces.
58
+ - **Shared module** (`components/`, `hooks/`, `lib/`): Owned by no single feature. Used by two or more features. Has no knowledge of any specific feature's business logic.
59
+
60
+ The rule: shared modules must have zero imports from feature modules. Feature modules may import from shared modules. This prevents circular dependencies and keeps shared code reusable.
61
+
62
+ ### Barrel Exports
63
+
64
+ Use `index.ts` barrel files at the feature and component directory level to create clean import paths:
65
+
66
+ ```typescript
67
+ // features/user-profile/index.ts
68
+ export { UserProfile } from "./UserProfile";
69
+ export { useUserProfile } from "./useUserProfile";
70
+ export type { UserProfileData } from "./user-profile.types";
71
+ ```
72
+
73
+ Consumers import from `features/user-profile`, not from deep internal paths:
74
+ ```typescript
75
+ // Good
76
+ import { UserProfile } from "@/features/user-profile";
77
+
78
+ // Bad — leaks internal structure
79
+ import { UserProfile } from "@/features/user-profile/components/UserProfile";
80
+ ```
81
+
82
+ Configure TypeScript path aliases (`@/`) to avoid relative path ladders (`../../../../../../`).
83
+
84
+ ### Config Files
85
+
86
+ Config files belong at the repo root, not inside `src/`. Standard placement:
87
+
88
+ - `next.config.ts` / `vite.config.ts` — build and bundler config
89
+ - `tsconfig.json` — TypeScript compiler config
90
+ - `eslint.config.js` — linting rules
91
+ - `.env.example` — documented environment variables (committed); `.env.local` — actual values (gitignored)
92
+ - `tailwind.config.ts` — if using Tailwind
93
+ - `vitest.config.ts` / `jest.config.ts` — test runner config
94
+
95
+ ### Feature Module Template
96
+
97
+ Every feature module follows the same internal structure. Establish this template in `CONTRIBUTING.md`:
98
+
99
+ ```
100
+ features/
101
+ <feature-name>/
102
+ index.ts # Barrel export — public API of the feature
103
+ <FeatureName>.tsx # Top-level feature component
104
+ <FeatureName>.test.tsx # Component tests
105
+ <FeatureName>.stories.tsx # Storybook stories (if applicable)
106
+ use<FeatureName>.ts # Primary data hook
107
+ use<FeatureName>.test.ts # Hook tests
108
+ <feature-name>.types.ts # TypeScript types for this feature
109
+ <feature-name>.api.ts # API calls made by this feature (if applicable)
110
+ components/ # Sub-components used only within this feature
111
+ <SubComponent>.tsx
112
+ ```
113
+
114
+ Enforce "no cross-feature imports" with ESLint:
115
+
116
+ ```javascript
117
+ // eslint-plugin-import rule to prevent cross-feature imports
118
+ "import/no-restricted-paths": [
119
+ "error",
120
+ {
121
+ "zones": [{
122
+ "target": "./src/features",
123
+ "from": "./src/features",
124
+ "except": ["./src/features/index.ts"] // Only barrel is importable
125
+ }]
126
+ }
127
+ ]
128
+ ```
129
+
130
+ ### Environment Variable Management
131
+
132
+ Never hardcode environment-specific values. Use `.env` files and document every variable:
133
+
134
+ ```bash
135
+ # .env.example — committed to the repo
136
+ # Never commit .env, .env.local, or .env.production
137
+
138
+ # API base URL
139
+ NEXT_PUBLIC_API_URL=https://api.example.com
140
+
141
+ # Auth provider
142
+ NEXT_PUBLIC_AUTH_DOMAIN=your-domain.auth0.com
143
+ AUTH_SECRET= # Server-only; never expose to client (no NEXT_PUBLIC_ prefix)
144
+
145
+ # Feature flags
146
+ NEXT_PUBLIC_FEATURE_NEW_CHECKOUT=false
147
+ ```
148
+
149
+ Validate environment variables at startup using a schema (Zod is ideal). Fail fast with a clear error message if required variables are missing or malformed. Never let the app silently run with bad configuration.
150
+
151
+ ### Avoiding the "Utils Dumping Ground"
152
+
153
+ A `utils/` directory with no sub-organization becomes a junk drawer within weeks. Apply the same discipline to utilities:
154
+
155
+ - Group by domain: `lib/date.ts`, `lib/currency.ts`, `lib/validation.ts`
156
+ - If a utility grows beyond ~100 lines, give it its own directory with an `index.ts`
157
+ - Delete utilities that are no longer used — dead code in `lib/` is worse than no code
158
+ - Never put business logic in `lib/`. Business logic belongs in features or hooks.
159
+
160
+ The test for whether something belongs in `lib/`: "Could I copy this to a different web app project without modification?" If yes, it belongs in `lib/`. If it has knowledge of this app's domain, it belongs in `features/` or `hooks/`.