@girardmedia/bootspring 3.3.2 → 3.4.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.
- package/assets/agents/accessibility-auditor.md +39 -0
- package/assets/agents/api-designer.md +40 -0
- package/assets/agents/auth-implementer.md +64 -0
- package/assets/agents/bug-hunter.md +42 -0
- package/assets/agents/bundle-analyzer.md +40 -0
- package/assets/agents/cache-optimizer.md +55 -0
- package/assets/agents/changelog-writer.md +55 -0
- package/assets/agents/ci-cd-builder.md +40 -0
- package/assets/agents/code-explainer.md +39 -0
- package/assets/agents/code-reviewer.md +39 -0
- package/assets/agents/cost-optimizer.md +57 -0
- package/assets/agents/cron-scheduler.md +51 -0
- package/assets/agents/data-seeder.md +56 -0
- package/assets/agents/database-architect.md +40 -0
- package/assets/agents/dependency-updater.md +40 -0
- package/assets/agents/deploy-checker.md +40 -0
- package/assets/agents/docker-optimizer.md +40 -0
- package/assets/agents/documentation-writer.md +40 -0
- package/assets/agents/email-builder.md +55 -0
- package/assets/agents/env-setup.md +40 -0
- package/assets/agents/error-handler.md +40 -0
- package/assets/agents/eslint-fixer.md +46 -0
- package/assets/agents/feature-flagger.md +69 -0
- package/assets/agents/git-detective.md +39 -0
- package/assets/agents/graphql-builder.md +60 -0
- package/assets/agents/incident-responder.md +59 -0
- package/assets/agents/log-analyzer.md +39 -0
- package/assets/agents/migration-planner.md +41 -0
- package/assets/agents/monorepo-navigator.md +39 -0
- package/assets/agents/nextjs-expert.md +57 -0
- package/assets/agents/notification-builder.md +56 -0
- package/assets/agents/onboarding-guide.md +39 -0
- package/assets/agents/performance-profiler.md +40 -0
- package/assets/agents/prisma-expert.md +57 -0
- package/assets/agents/rate-limiter.md +58 -0
- package/assets/agents/react-expert.md +58 -0
- package/assets/agents/refactorer.md +42 -0
- package/assets/agents/regex-builder.md +46 -0
- package/assets/agents/release-manager.md +40 -0
- package/assets/agents/s3-manager.md +58 -0
- package/assets/agents/schema-validator.md +40 -0
- package/assets/agents/search-builder.md +62 -0
- package/assets/agents/security-auditor.md +39 -0
- package/assets/agents/sitemap-generator.md +53 -0
- package/assets/agents/stripe-integrator.md +59 -0
- package/assets/agents/tailwind-expert.md +55 -0
- package/assets/agents/tech-debt-tracker.md +39 -0
- package/assets/agents/test-writer.md +42 -0
- package/assets/agents/type-fixer.md +45 -0
- package/assets/agents/webhook-builder.md +54 -0
- package/assets/rules/cpp.md +53 -0
- package/assets/rules/css.md +52 -0
- package/assets/rules/go.md +50 -0
- package/assets/rules/html.md +52 -0
- package/assets/rules/java.md +51 -0
- package/assets/rules/kotlin.md +50 -0
- package/assets/rules/php.md +51 -0
- package/assets/rules/python.md +51 -0
- package/assets/rules/ruby.md +51 -0
- package/assets/rules/rust.md +49 -0
- package/assets/rules/shell.md +52 -0
- package/assets/rules/sql.md +49 -0
- package/assets/rules/swift.md +50 -0
- package/assets/rules/typescript.md +52 -0
- package/assets/rules/yaml-json.md +51 -0
- package/assets/skills/accessibility.md +210 -0
- package/assets/skills/agent-patterns.md +387 -0
- package/assets/skills/ai-integration.md +263 -0
- package/assets/skills/animation-patterns.md +224 -0
- package/assets/skills/api-design.md +218 -0
- package/assets/skills/api-gateway.md +341 -0
- package/assets/skills/api-versioning.md +226 -0
- package/assets/skills/astro-patterns.md +233 -0
- package/assets/skills/auth-patterns.md +248 -0
- package/assets/skills/aws-patterns.md +171 -0
- package/assets/skills/background-jobs.md +162 -0
- package/assets/skills/browser-extensions.md +309 -0
- package/assets/skills/caching-patterns.md +253 -0
- package/assets/skills/ci-cd.md +251 -0
- package/assets/skills/cli-development.md +296 -0
- package/assets/skills/code-review.md +185 -0
- package/assets/skills/cron-patterns.md +327 -0
- package/assets/skills/data-fetching.md +231 -0
- package/assets/skills/database-migrations.md +346 -0
- package/assets/skills/database-patterns.md +219 -0
- package/assets/skills/debugging.md +281 -0
- package/assets/skills/design-system.md +289 -0
- package/assets/skills/django-patterns.md +182 -0
- package/assets/skills/docker-patterns.md +235 -0
- package/assets/skills/e2e-testing.md +287 -0
- package/assets/skills/edge-computing.md +268 -0
- package/assets/skills/electron-patterns.md +266 -0
- package/assets/skills/email-templates.md +206 -0
- package/assets/skills/error-handling.md +265 -0
- package/assets/skills/event-driven.md +232 -0
- package/assets/skills/express-patterns.md +239 -0
- package/assets/skills/fastapi-patterns.md +198 -0
- package/assets/skills/feature-flags.md +212 -0
- package/assets/skills/figma-to-code.md +298 -0
- package/assets/skills/file-upload.md +228 -0
- package/assets/skills/forms-patterns.md +264 -0
- package/assets/skills/gcp-patterns.md +189 -0
- package/assets/skills/git-workflow.md +187 -0
- package/assets/skills/golang-patterns.md +185 -0
- package/assets/skills/graphql-patterns.md +244 -0
- package/assets/skills/i18n-patterns.md +172 -0
- package/assets/skills/image-processing.md +350 -0
- package/assets/skills/java-springboot.md +226 -0
- package/assets/skills/kotlin-patterns.md +207 -0
- package/assets/skills/kubernetes-patterns.md +326 -0
- package/assets/skills/laravel-patterns.md +261 -0
- package/assets/skills/llm-fine-tuning.md +335 -0
- package/assets/skills/load-testing.md +303 -0
- package/assets/skills/logging-observability.md +228 -0
- package/assets/skills/markdown-processing.md +318 -0
- package/assets/skills/mcp-server-patterns.md +292 -0
- package/assets/skills/microservices.md +272 -0
- package/assets/skills/migration-patterns.md +239 -0
- package/assets/skills/mongodb-patterns.md +189 -0
- package/assets/skills/monorepo-patterns.md +287 -0
- package/assets/skills/nextjs-app-router.md +237 -0
- package/assets/skills/notification-patterns.md +348 -0
- package/assets/skills/oauth-patterns.md +246 -0
- package/assets/skills/payment-integration.md +222 -0
- package/assets/skills/pdf-generation.md +307 -0
- package/assets/skills/performance-optimization.md +277 -0
- package/assets/skills/php-patterns.md +210 -0
- package/assets/skills/prisma-patterns.md +241 -0
- package/assets/skills/prompt-engineering.md +193 -0
- package/assets/skills/pwa-patterns.md +247 -0
- package/assets/skills/python-patterns.md +158 -0
- package/assets/skills/python-testing.md +172 -0
- package/assets/skills/queue-patterns.md +295 -0
- package/assets/skills/rag-patterns.md +159 -0
- package/assets/skills/rate-limiting.md +319 -0
- package/assets/skills/react-components.md +201 -0
- package/assets/skills/react-native-patterns.md +299 -0
- package/assets/skills/real-time-patterns.md +181 -0
- package/assets/skills/redis-patterns.md +188 -0
- package/assets/skills/refactoring.md +218 -0
- package/assets/skills/regex-patterns.md +191 -0
- package/assets/skills/remix-patterns.md +262 -0
- package/assets/skills/responsive-design.md +199 -0
- package/assets/skills/ruby-rails-patterns.md +178 -0
- package/assets/skills/rust-patterns.md +211 -0
- package/assets/skills/search-patterns.md +227 -0
- package/assets/skills/security-hardening.md +237 -0
- package/assets/skills/seo-patterns.md +179 -0
- package/assets/skills/serverless-patterns.md +223 -0
- package/assets/skills/sql-optimization.md +154 -0
- package/assets/skills/state-management.md +254 -0
- package/assets/skills/storybook-patterns.md +330 -0
- package/assets/skills/svelte-patterns.md +258 -0
- package/assets/skills/swift-patterns.md +227 -0
- package/assets/skills/tailwind-patterns.md +272 -0
- package/assets/skills/tdd-workflow.md +199 -0
- package/assets/skills/terraform-patterns.md +270 -0
- package/assets/skills/testing-react.md +240 -0
- package/assets/skills/testing-vitest.md +232 -0
- package/assets/skills/typescript-strict.md +159 -0
- package/assets/skills/video-processing.md +340 -0
- package/assets/skills/vue-patterns.md +247 -0
- package/assets/skills/web-workers.md +327 -0
- package/assets/skills/webhooks-patterns.md +283 -0
- package/assets/skills/websocket-patterns.md +306 -0
- package/dist/cli/index.js +941 -958
- package/dist/core/index.d.ts +341 -11
- package/dist/core.js +58 -95
- package/dist/mcp/index.d.ts +33 -1
- package/dist/mcp-server.js +177 -255
- package/package.json +4 -1
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: monorepo-patterns
|
|
3
|
+
description: Structure monorepos with Turborepo — workspace dependencies, shared packages, build caching, and task pipelines.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Monorepo Patterns
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
|
|
10
|
+
Use a monorepo when you have multiple packages or apps that share code,
|
|
11
|
+
configuration, or release cycles. A monorepo eliminates version drift between
|
|
12
|
+
packages, simplifies cross-cutting refactors, and enables atomic commits across
|
|
13
|
+
your entire system. These patterns focus on Turborepo with npm/pnpm workspaces.
|
|
14
|
+
|
|
15
|
+
## How It Works
|
|
16
|
+
|
|
17
|
+
### 1. Workspace Structure
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
monorepo/
|
|
21
|
+
apps/
|
|
22
|
+
web/ ← Next.js frontend
|
|
23
|
+
api/ ← Express API server
|
|
24
|
+
cli/ ← CLI tool
|
|
25
|
+
docs/ ← Documentation site
|
|
26
|
+
packages/
|
|
27
|
+
ui/ ← Shared React components
|
|
28
|
+
core/ ← Auth, API client, config
|
|
29
|
+
tsconfig/ ← Shared TypeScript configs
|
|
30
|
+
eslint-config/ ← Shared ESLint configs
|
|
31
|
+
turbo.json
|
|
32
|
+
package.json
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Root `package.json`:
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"private": true,
|
|
40
|
+
"workspaces": ["apps/*", "packages/*"],
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"turbo": "^2.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. Workspace Dependencies
|
|
48
|
+
|
|
49
|
+
Reference internal packages by name. No `file:` or `link:` prefixes needed
|
|
50
|
+
with modern workspaces.
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
// apps/web/package.json
|
|
54
|
+
{
|
|
55
|
+
"name": "@myorg/web",
|
|
56
|
+
"dependencies": {
|
|
57
|
+
"@myorg/ui": "workspace:*",
|
|
58
|
+
"@myorg/core": "workspace:*"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
// packages/ui/package.json
|
|
65
|
+
{
|
|
66
|
+
"name": "@myorg/ui",
|
|
67
|
+
"main": "./dist/index.js",
|
|
68
|
+
"types": "./dist/index.d.ts",
|
|
69
|
+
"exports": {
|
|
70
|
+
".": { "import": "./dist/index.js", "types": "./dist/index.d.ts" },
|
|
71
|
+
"./button": { "import": "./dist/button.js", "types": "./dist/button.d.ts" }
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"build": "tsup src/index.ts --format esm --dts",
|
|
75
|
+
"dev": "tsup src/index.ts --format esm --dts --watch"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 3. Shared TypeScript Config
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
// packages/tsconfig/base.json
|
|
84
|
+
{
|
|
85
|
+
"compilerOptions": {
|
|
86
|
+
"strict": true,
|
|
87
|
+
"target": "ES2022",
|
|
88
|
+
"module": "ESNext",
|
|
89
|
+
"moduleResolution": "bundler",
|
|
90
|
+
"esModuleInterop": true,
|
|
91
|
+
"skipLibCheck": true,
|
|
92
|
+
"declaration": true,
|
|
93
|
+
"declarationMap": true,
|
|
94
|
+
"sourceMap": true,
|
|
95
|
+
"noUncheckedIndexedAccess": true
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// packages/tsconfig/nextjs.json
|
|
100
|
+
{
|
|
101
|
+
"extends": "./base.json",
|
|
102
|
+
"compilerOptions": {
|
|
103
|
+
"jsx": "preserve",
|
|
104
|
+
"lib": ["dom", "dom.iterable", "ES2022"],
|
|
105
|
+
"module": "ESNext",
|
|
106
|
+
"plugins": [{ "name": "next" }]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Apps extend the shared config:
|
|
112
|
+
|
|
113
|
+
```json
|
|
114
|
+
// apps/web/tsconfig.json
|
|
115
|
+
{
|
|
116
|
+
"extends": "@myorg/tsconfig/nextjs.json",
|
|
117
|
+
"include": ["src", "next-env.d.ts"],
|
|
118
|
+
"exclude": ["node_modules"]
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 4. Turborepo Task Pipeline
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
// turbo.json
|
|
126
|
+
{
|
|
127
|
+
"$schema": "https://turbo.build/schema.json",
|
|
128
|
+
"tasks": {
|
|
129
|
+
"build": {
|
|
130
|
+
"dependsOn": ["^build"],
|
|
131
|
+
"outputs": ["dist/**", ".next/**"],
|
|
132
|
+
"env": ["NODE_ENV"]
|
|
133
|
+
},
|
|
134
|
+
"dev": {
|
|
135
|
+
"dependsOn": ["^build"],
|
|
136
|
+
"cache": false,
|
|
137
|
+
"persistent": true
|
|
138
|
+
},
|
|
139
|
+
"test": {
|
|
140
|
+
"dependsOn": ["^build"],
|
|
141
|
+
"outputs": ["coverage/**"],
|
|
142
|
+
"env": ["CI"]
|
|
143
|
+
},
|
|
144
|
+
"lint": {
|
|
145
|
+
"dependsOn": ["^build"]
|
|
146
|
+
},
|
|
147
|
+
"typecheck": {
|
|
148
|
+
"dependsOn": ["^build"]
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
`^build` means: build all dependencies first. Turbo automatically determines
|
|
155
|
+
the correct order from workspace dependency graph.
|
|
156
|
+
|
|
157
|
+
### 5. Build Caching
|
|
158
|
+
|
|
159
|
+
Turbo caches task outputs based on file inputs, environment variables, and
|
|
160
|
+
dependency graph. Unchanged packages skip rebuilding.
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# First run: builds everything (~60s)
|
|
164
|
+
turbo run build
|
|
165
|
+
|
|
166
|
+
# Second run: all cached (~1s)
|
|
167
|
+
turbo run build
|
|
168
|
+
|
|
169
|
+
# After changing packages/ui: rebuilds ui + apps that depend on it
|
|
170
|
+
turbo run build
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Remote caching shares build artifacts across CI and developers:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Enable remote cache (Vercel)
|
|
177
|
+
npx turbo login
|
|
178
|
+
npx turbo link
|
|
179
|
+
|
|
180
|
+
# CI: use remote cache
|
|
181
|
+
TURBO_TOKEN=${{ secrets.TURBO_TOKEN }} turbo run build
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 6. Filtering — Run Tasks for Specific Packages
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Build only the web app and its dependencies
|
|
188
|
+
turbo run build --filter=@myorg/web...
|
|
189
|
+
|
|
190
|
+
# Test only packages that changed since main
|
|
191
|
+
turbo run test --filter=...[main]
|
|
192
|
+
|
|
193
|
+
# Run dev for web + all its dependencies
|
|
194
|
+
turbo run dev --filter=@myorg/web...
|
|
195
|
+
|
|
196
|
+
# Build only packages in the packages/ directory
|
|
197
|
+
turbo run build --filter='./packages/*'
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### 7. Shared ESLint Config
|
|
201
|
+
|
|
202
|
+
```javascript
|
|
203
|
+
// packages/eslint-config/base.js
|
|
204
|
+
module.exports = {
|
|
205
|
+
parser: '@typescript-eslint/parser',
|
|
206
|
+
extends: [
|
|
207
|
+
'eslint:recommended',
|
|
208
|
+
'plugin:@typescript-eslint/recommended',
|
|
209
|
+
'prettier',
|
|
210
|
+
],
|
|
211
|
+
rules: {
|
|
212
|
+
'@typescript-eslint/no-explicit-any': 'error',
|
|
213
|
+
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// packages/eslint-config/react.js
|
|
218
|
+
module.exports = {
|
|
219
|
+
extends: ['./base.js', 'plugin:react/recommended', 'plugin:react-hooks/recommended'],
|
|
220
|
+
settings: { react: { version: 'detect' } },
|
|
221
|
+
};
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### 8. Publishing from a Monorepo
|
|
225
|
+
|
|
226
|
+
Use changesets for versioning and publishing.
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
# Add a changeset when making changes
|
|
230
|
+
npx changeset
|
|
231
|
+
|
|
232
|
+
# Version packages (bumps versions, updates changelogs)
|
|
233
|
+
npx changeset version
|
|
234
|
+
|
|
235
|
+
# Publish changed packages
|
|
236
|
+
npx changeset publish
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
// .changeset/config.json
|
|
241
|
+
{
|
|
242
|
+
"changelog": "@changesets/cli/changelog",
|
|
243
|
+
"commit": false,
|
|
244
|
+
"access": "restricted",
|
|
245
|
+
"baseBranch": "main",
|
|
246
|
+
"updateInternalDependencies": "patch"
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### 9. Common Scripts
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
// Root package.json
|
|
254
|
+
{
|
|
255
|
+
"scripts": {
|
|
256
|
+
"dev": "turbo run dev",
|
|
257
|
+
"build": "turbo run build",
|
|
258
|
+
"test": "turbo run test",
|
|
259
|
+
"lint": "turbo run lint",
|
|
260
|
+
"typecheck": "turbo run typecheck",
|
|
261
|
+
"clean": "turbo run clean && rm -rf node_modules",
|
|
262
|
+
"format": "prettier --write \"**/*.{ts,tsx,md,json}\""
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Examples
|
|
268
|
+
|
|
269
|
+
| Need | Command |
|
|
270
|
+
|------|---------|
|
|
271
|
+
| Build everything | `turbo run build` |
|
|
272
|
+
| Dev mode for web + deps | `turbo run dev --filter=@myorg/web...` |
|
|
273
|
+
| Test changed packages | `turbo run test --filter=...[main]` |
|
|
274
|
+
| Add shared dependency | `npm install zod -w packages/core` |
|
|
275
|
+
| Add devDependency to root | `npm install -D prettier -w .` |
|
|
276
|
+
|
|
277
|
+
## Checklist
|
|
278
|
+
|
|
279
|
+
- [ ] Workspace packages use `workspace:*` for internal dependencies
|
|
280
|
+
- [ ] Shared configs (tsconfig, eslint, prettier) live in `packages/`
|
|
281
|
+
- [ ] `turbo.json` defines task dependencies with `^build` for correct ordering
|
|
282
|
+
- [ ] Build outputs are listed in `turbo.json` for proper caching
|
|
283
|
+
- [ ] Remote caching is enabled for CI (Vercel or self-hosted)
|
|
284
|
+
- [ ] `--filter` is used in CI to only build/test affected packages
|
|
285
|
+
- [ ] Each package has its own `build`, `test`, and `lint` scripts
|
|
286
|
+
- [ ] Changesets manage versioning for published packages
|
|
287
|
+
- [ ] Root `package.json` is `"private": true` and only contains workspace scripts
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs-app-router
|
|
3
|
+
description: Leverage Next.js App Router features — server components, streaming, parallel routes, and server actions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Next.js App Router Patterns
|
|
7
|
+
|
|
8
|
+
## When to Use
|
|
9
|
+
|
|
10
|
+
Use these patterns when building Next.js 13+ applications with the App Router.
|
|
11
|
+
Server components, streaming, and server actions fundamentally change how you
|
|
12
|
+
structure data fetching, layouts, and mutations compared to the Pages Router.
|
|
13
|
+
|
|
14
|
+
## How It Works
|
|
15
|
+
|
|
16
|
+
### 1. Server Components by Default
|
|
17
|
+
|
|
18
|
+
Every component in `app/` is a server component unless you add `'use client'`.
|
|
19
|
+
Keep the client boundary as low as possible.
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
app/
|
|
23
|
+
dashboard/
|
|
24
|
+
page.tsx ← server component (fetches data directly)
|
|
25
|
+
_components/
|
|
26
|
+
chart.tsx ← 'use client' (needs browser APIs)
|
|
27
|
+
stats-card.tsx ← server component (static render)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
// app/dashboard/page.tsx — no 'use client', runs on the server
|
|
32
|
+
import { db } from '@/lib/db';
|
|
33
|
+
|
|
34
|
+
export default async function DashboardPage() {
|
|
35
|
+
const stats = await db.stats.findMany(); // direct DB access, no API route
|
|
36
|
+
return (
|
|
37
|
+
<div>
|
|
38
|
+
<StatsCard data={stats} />
|
|
39
|
+
<Chart data={stats} /> {/* client component for interactivity */}
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Rule: if it doesn't need `useState`, `useEffect`, event handlers, or browser
|
|
46
|
+
APIs, it stays a server component.
|
|
47
|
+
|
|
48
|
+
### 2. Loading and Error UI
|
|
49
|
+
|
|
50
|
+
Place `loading.tsx` and `error.tsx` alongside `page.tsx` for automatic Suspense
|
|
51
|
+
and error boundary wrapping.
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
// app/dashboard/loading.tsx
|
|
55
|
+
export default function Loading() {
|
|
56
|
+
return <DashboardSkeleton />;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// app/dashboard/error.tsx
|
|
60
|
+
'use client'; // error.tsx must be a client component
|
|
61
|
+
|
|
62
|
+
export default function Error({ error, reset }: {
|
|
63
|
+
error: Error & { digest?: string };
|
|
64
|
+
reset: () => void;
|
|
65
|
+
}) {
|
|
66
|
+
return (
|
|
67
|
+
<div role="alert">
|
|
68
|
+
<h2>Something went wrong</h2>
|
|
69
|
+
<p>{error.message}</p>
|
|
70
|
+
<button onClick={reset}>Try again</button>
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Also use `not-found.tsx` with `notFound()` from `next/navigation` for 404 pages.
|
|
77
|
+
|
|
78
|
+
### 3. Parallel Routes
|
|
79
|
+
|
|
80
|
+
Render multiple pages in the same layout simultaneously using named slots.
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
app/
|
|
84
|
+
@analytics/
|
|
85
|
+
page.tsx
|
|
86
|
+
loading.tsx
|
|
87
|
+
@activity/
|
|
88
|
+
page.tsx
|
|
89
|
+
loading.tsx
|
|
90
|
+
layout.tsx
|
|
91
|
+
page.tsx
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
// app/layout.tsx
|
|
96
|
+
export default function Layout({
|
|
97
|
+
children,
|
|
98
|
+
analytics,
|
|
99
|
+
activity,
|
|
100
|
+
}: {
|
|
101
|
+
children: ReactNode;
|
|
102
|
+
analytics: ReactNode;
|
|
103
|
+
activity: ReactNode;
|
|
104
|
+
}) {
|
|
105
|
+
return (
|
|
106
|
+
<div className="grid grid-cols-3">
|
|
107
|
+
<main className="col-span-2">{children}</main>
|
|
108
|
+
<aside>
|
|
109
|
+
{analytics}
|
|
110
|
+
{activity}
|
|
111
|
+
</aside>
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Each slot streams independently — fast panels appear first, slow panels show
|
|
118
|
+
their own loading state.
|
|
119
|
+
|
|
120
|
+
### 4. Intercepting Routes
|
|
121
|
+
|
|
122
|
+
Show a modal on soft navigation while keeping the full page accessible via
|
|
123
|
+
direct URL.
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
app/
|
|
127
|
+
photos/
|
|
128
|
+
[id]/
|
|
129
|
+
page.tsx ← full page (direct URL or hard refresh)
|
|
130
|
+
@modal/
|
|
131
|
+
(.)photos/[id]/
|
|
132
|
+
page.tsx ← intercepted modal (soft navigation)
|
|
133
|
+
default.tsx ← returns null when no modal is active
|
|
134
|
+
layout.tsx
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The `(.)` prefix intercepts one level up. Use `(..)` for two levels, `(...)` for root.
|
|
138
|
+
|
|
139
|
+
### 5. Server Actions
|
|
140
|
+
|
|
141
|
+
Mutate data without API routes. Define with `'use server'` and use in forms or
|
|
142
|
+
call from client components.
|
|
143
|
+
|
|
144
|
+
```tsx
|
|
145
|
+
// app/actions/user.ts
|
|
146
|
+
'use server';
|
|
147
|
+
|
|
148
|
+
import { revalidatePath } from 'next/cache';
|
|
149
|
+
import { db } from '@/lib/db';
|
|
150
|
+
import { z } from 'zod';
|
|
151
|
+
|
|
152
|
+
const UpdateProfileSchema = z.object({
|
|
153
|
+
name: z.string().min(1).max(100),
|
|
154
|
+
bio: z.string().max(500),
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
export async function updateProfile(formData: FormData) {
|
|
158
|
+
const parsed = UpdateProfileSchema.safeParse({
|
|
159
|
+
name: formData.get('name'),
|
|
160
|
+
bio: formData.get('bio'),
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
if (!parsed.success) {
|
|
164
|
+
return { error: parsed.error.flatten().fieldErrors };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
await db.user.update({ where: { id: getCurrentUserId() }, data: parsed.data });
|
|
168
|
+
revalidatePath('/profile');
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
// app/profile/edit/page.tsx
|
|
174
|
+
import { updateProfile } from '@/app/actions/user';
|
|
175
|
+
|
|
176
|
+
export default function EditProfile() {
|
|
177
|
+
return (
|
|
178
|
+
<form action={updateProfile}>
|
|
179
|
+
<input name="name" required />
|
|
180
|
+
<textarea name="bio" />
|
|
181
|
+
<button type="submit">Save</button>
|
|
182
|
+
</form>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 6. Metadata and SEO
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
// app/blog/[slug]/page.tsx
|
|
191
|
+
import type { Metadata } from 'next';
|
|
192
|
+
|
|
193
|
+
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
|
194
|
+
const post = await getPost(params.slug);
|
|
195
|
+
return {
|
|
196
|
+
title: post.title,
|
|
197
|
+
description: post.excerpt,
|
|
198
|
+
openGraph: { images: [post.coverImage] },
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### 7. Route Groups for Organization
|
|
204
|
+
|
|
205
|
+
Use `(groupName)` folders to organize without affecting URLs.
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
app/
|
|
209
|
+
(marketing)/
|
|
210
|
+
about/page.tsx → /about
|
|
211
|
+
pricing/page.tsx → /pricing
|
|
212
|
+
layout.tsx ← shared marketing layout
|
|
213
|
+
(dashboard)/
|
|
214
|
+
settings/page.tsx → /settings
|
|
215
|
+
layout.tsx ← shared dashboard layout (with sidebar)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Examples
|
|
219
|
+
|
|
220
|
+
| Need | Pattern | File |
|
|
221
|
+
|------|---------|------|
|
|
222
|
+
| Loading skeleton | `loading.tsx` | Auto-wrapped Suspense boundary |
|
|
223
|
+
| Error recovery | `error.tsx` + `reset()` | Auto-wrapped error boundary |
|
|
224
|
+
| Side-by-side panels | Parallel routes (`@slot`) | Independent streaming |
|
|
225
|
+
| Modal over list | Intercepting routes `(.)` | Modal on click, full page on refresh |
|
|
226
|
+
| Form mutation | Server action | No API route, automatic revalidation |
|
|
227
|
+
|
|
228
|
+
## Checklist
|
|
229
|
+
|
|
230
|
+
- [ ] Components default to server — `'use client'` only where browser APIs are needed
|
|
231
|
+
- [ ] Every route segment with async data has a `loading.tsx`
|
|
232
|
+
- [ ] Every route segment has an `error.tsx` with a retry button
|
|
233
|
+
- [ ] Server actions validate input with Zod before touching the database
|
|
234
|
+
- [ ] `revalidatePath` or `revalidateTag` is called after every mutation
|
|
235
|
+
- [ ] Metadata is generated dynamically for pages with variable content
|
|
236
|
+
- [ ] Route groups separate marketing pages from authenticated dashboard
|
|
237
|
+
- [ ] No `fetch` calls to your own API routes from server components — query the DB directly
|