groundwork-method 0.0.1 → 0.11.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/CHANGELOG.md +823 -0
- package/LICENSE +21 -0
- package/README.md +44 -29
- package/bin/groundwork.js +1723 -0
- package/dist/src/generators/add-capability/generator.d.ts +8 -0
- package/dist/src/generators/add-capability/generator.js +60 -0
- package/dist/src/generators/add-capability/generator.js.map +1 -0
- package/dist/src/generators/cli-app/generator.d.ts +9 -0
- package/dist/src/generators/cli-app/generator.js +140 -0
- package/dist/src/generators/cli-app/generator.js.map +1 -0
- package/dist/src/generators/docs-site/generator.d.ts +5 -0
- package/dist/src/generators/docs-site/generator.js +441 -0
- package/dist/src/generators/docs-site/generator.js.map +1 -0
- package/dist/src/generators/electron-app/generator.d.ts +6 -0
- package/dist/src/generators/electron-app/generator.js +261 -0
- package/dist/src/generators/electron-app/generator.js.map +1 -0
- package/dist/src/generators/flutter-app/generator.d.ts +6 -0
- package/dist/src/generators/flutter-app/generator.js +314 -0
- package/dist/src/generators/flutter-app/generator.js.map +1 -0
- package/dist/src/generators/go-microservice/generator.d.ts +8 -0
- package/dist/src/generators/go-microservice/generator.js +232 -0
- package/dist/src/generators/go-microservice/generator.js.map +1 -0
- package/dist/src/generators/nextjs-app/generator.d.ts +8 -0
- package/dist/src/generators/nextjs-app/generator.js +294 -0
- package/dist/src/generators/nextjs-app/generator.js.map +1 -0
- package/dist/src/generators/python-microservice/generator.d.ts +13 -0
- package/dist/src/generators/python-microservice/generator.js +265 -0
- package/dist/src/generators/python-microservice/generator.js.map +1 -0
- package/dist/src/generators/shared/brand-tokens.d.ts +89 -0
- package/dist/src/generators/shared/brand-tokens.js +308 -0
- package/dist/src/generators/shared/brand-tokens.js.map +1 -0
- package/dist/src/generators/shared/capabilities.d.ts +101 -0
- package/dist/src/generators/shared/capabilities.js +279 -0
- package/dist/src/generators/shared/capabilities.js.map +1 -0
- package/dist/src/generators/shared/provenance.d.ts +2 -0
- package/dist/src/generators/shared/provenance.js +85 -0
- package/dist/src/generators/shared/provenance.js.map +1 -0
- package/dist/src/generators/shared/scaffold-helpers.d.ts +72 -0
- package/dist/src/generators/shared/scaffold-helpers.js +309 -0
- package/dist/src/generators/shared/scaffold-helpers.js.map +1 -0
- package/dist/src/generators/system-test-runner/generator.d.ts +23 -0
- package/dist/src/generators/system-test-runner/generator.js +173 -0
- package/dist/src/generators/system-test-runner/generator.js.map +1 -0
- package/dist/src/generators/workspace-dev-cli/generator.d.ts +7 -0
- package/dist/src/generators/workspace-dev-cli/generator.js +138 -0
- package/dist/src/generators/workspace-dev-cli/generator.js.map +1 -0
- package/generators.json +57 -0
- package/lib/repo-map/grammars/tree-sitter-c.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-cpp.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-csharp.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-dart.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-go.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-java.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-javascript.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-kotlin.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-lua.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-php.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-python.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-ruby.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-rust.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-scala.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-swift.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-tsx.wasm +0 -0
- package/lib/repo-map/grammars/tree-sitter-typescript.wasm +0 -0
- package/lib/repo-map/index.js +386 -0
- package/lib/repo-map/languages.js +514 -0
- package/lib/repo-map/pagerank.js +59 -0
- package/migrations/README.md +60 -0
- package/migrations/_template/cli-migration.js +27 -0
- package/migrations/gw-bet-prose-redesign.js +105 -0
- package/migrations/gw-drop-test-manifest.js +37 -0
- package/migrations/gw-register-serena-mcp.js +42 -0
- package/migrations/gw-relocate-hidden-skills.js +40 -0
- package/migrations/gw-seed-config-toml.js +24 -0
- package/migrations/index.json +40 -0
- package/package.json +70 -6
- package/src/AGENTS.md +36 -0
- package/src/config/config.toml +30 -0
- package/src/config/groundwork-state.json +5 -0
- package/src/docs/llms.txt +72 -0
- package/src/docs/principles/ai-native/agent-native-systems.md +90 -0
- package/src/docs/principles/ai-native/agentic-systems.md +78 -0
- package/src/docs/principles/ai-native/ai-engineering.md +100 -0
- package/src/docs/principles/ai-native/ai-native-product.md +76 -0
- package/src/docs/principles/delivery/cost-engineering.md +89 -0
- package/src/docs/principles/delivery/day-2-operational-baseline.md +57 -0
- package/src/docs/principles/delivery/devex.md +88 -0
- package/src/docs/principles/delivery/platform.md +101 -0
- package/src/docs/principles/delivery/progressive-delivery.md +92 -0
- package/src/docs/principles/design/ai-native-design.md +73 -0
- package/src/docs/principles/design/design-foundations.md +80 -0
- package/src/docs/principles/design/design-systems-and-tokens.md +72 -0
- package/src/docs/principles/design/interaction-and-motion.md +69 -0
- package/src/docs/principles/design/layout-and-space.md +72 -0
- package/src/docs/principles/design/usability-and-ux.md +79 -0
- package/src/docs/principles/design/visual-design.md +84 -0
- package/src/docs/principles/foundations/code-craft.md +86 -0
- package/src/docs/principles/foundations/continuous-discovery.md +75 -0
- package/src/docs/principles/foundations/documentation.md +102 -0
- package/src/docs/principles/foundations/prioritization-and-appetite.md +78 -0
- package/src/docs/principles/foundations/product-engineering.md +90 -0
- package/src/docs/principles/foundations/product-risks.md +89 -0
- package/src/docs/principles/foundations/requirements-and-specs.md +80 -0
- package/src/docs/principles/foundations/success-metrics.md +66 -0
- package/src/docs/principles/foundations/testing.md +108 -0
- package/src/docs/principles/index.md +24 -0
- package/src/docs/principles/quality/accessibility.md +88 -0
- package/src/docs/principles/quality/observability.md +84 -0
- package/src/docs/principles/quality/performance.md +84 -0
- package/src/docs/principles/quality/privacy.md +92 -0
- package/src/docs/principles/quality/reliability.md +89 -0
- package/src/docs/principles/quality/security.md +78 -0
- package/src/docs/principles/stack/postgres.md +100 -0
- package/src/docs/principles/system-design/api-design.md +86 -0
- package/src/docs/principles/system-design/architecture-decisions.md +81 -0
- package/src/docs/principles/system-design/code-structure.md +104 -0
- package/src/docs/principles/system-design/data-engineering.md +87 -0
- package/src/docs/principles/system-design/durable-execution.md +89 -0
- package/src/docs/principles/system-design/evolutionary-architecture.md +81 -0
- package/src/docs/principles/system-design/identity-and-access.md +76 -0
- package/src/docs/principles/system-design/integration-patterns.md +84 -0
- package/src/docs/principles/system-design/real-time.md +83 -0
- package/src/docs/principles/system-design/surface-architecture.md +74 -0
- package/src/docs/ways-of-working/documentation.md +69 -0
- package/src/docs/ways-of-working/how-we-work.md +76 -0
- package/src/docs/ways-of-working/units-of-work.md +40 -0
- package/src/engineer-skills/groundwork-electron-engineer/SKILL.md +123 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/documentation.md +126 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/ipc-contracts.md +138 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/observability.md +37 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/packaging-and-updates.md +82 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/performance-and-reliability.md +80 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/process-model.md +94 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/security.md +107 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/testing-and-smoke.md +129 -0
- package/src/engineer-skills/groundwork-electron-engineer/references/theming-and-tokens.md +74 -0
- package/src/engineer-skills/groundwork-electron-engineer/sync-anchor.md +22 -0
- package/src/engineer-skills/groundwork-flutter-engineer/SKILL.md +114 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/accessibility.md +92 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/architecture.md +189 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/data-and-contracts.md +136 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/documentation.md +122 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/navigation.md +122 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/observability.md +37 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/performance-and-reliability.md +100 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/platform-channels.md +93 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/releases-and-distribution.md +84 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/security.md +96 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/state-management.md +166 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/testing.md +160 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/theming-and-design-tokens.md +109 -0
- package/src/engineer-skills/groundwork-flutter-engineer/references/widgets-and-composition.md +123 -0
- package/src/engineer-skills/groundwork-flutter-engineer/sync-anchor.md +24 -0
- package/src/engineer-skills/groundwork-go-engineer/SKILL.md +174 -0
- package/src/engineer-skills/groundwork-go-engineer/references/api-design.md +82 -0
- package/src/engineer-skills/groundwork-go-engineer/references/architecture.md +42 -0
- package/src/engineer-skills/groundwork-go-engineer/references/capability-ports.md +50 -0
- package/src/engineer-skills/groundwork-go-engineer/references/code-craft-security.md +34 -0
- package/src/engineer-skills/groundwork-go-engineer/references/concurrency.md +108 -0
- package/src/engineer-skills/groundwork-go-engineer/references/documentation.md +130 -0
- package/src/engineer-skills/groundwork-go-engineer/references/go-services.md +77 -0
- package/src/engineer-skills/groundwork-go-engineer/references/http-handlers.md +172 -0
- package/src/engineer-skills/groundwork-go-engineer/references/implementation-patterns.md +156 -0
- package/src/engineer-skills/groundwork-go-engineer/references/integration-realtime-data.md +57 -0
- package/src/engineer-skills/groundwork-go-engineer/references/observability.md +49 -0
- package/src/engineer-skills/groundwork-go-engineer/references/postgres.md +41 -0
- package/src/engineer-skills/groundwork-go-engineer/references/reliability-performance.md +105 -0
- package/src/engineer-skills/groundwork-go-engineer/references/testing.md +201 -0
- package/src/engineer-skills/groundwork-go-engineer/sync-anchor.md +20 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/SKILL.md +112 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/accessibility.md +111 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/architecture.md +323 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/data-fetching.md +458 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/documentation.md +324 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/error-boundaries.md +383 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/mutations-and-forms.md +396 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/observability.md +48 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/performance-and-deployment.md +947 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/routing-and-navigation.md +405 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/security.md +131 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/server-components.md +394 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/tailwind-and-styling.md +134 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/testing.md +491 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/type-system.md +368 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/ux-principles.md +230 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/references/visual-language.md +69 -0
- package/src/engineer-skills/groundwork-nextjs-engineer/sync-anchor.md +16 -0
- package/src/engineer-skills/groundwork-python-engineer/SKILL.md +199 -0
- package/src/engineer-skills/groundwork-python-engineer/references/api-standards.md +88 -0
- package/src/engineer-skills/groundwork-python-engineer/references/architecture.md +57 -0
- package/src/engineer-skills/groundwork-python-engineer/references/async-patterns.md +103 -0
- package/src/engineer-skills/groundwork-python-engineer/references/capability-ports.md +44 -0
- package/src/engineer-skills/groundwork-python-engineer/references/database.md +88 -0
- package/src/engineer-skills/groundwork-python-engineer/references/documentation-mcp.md +167 -0
- package/src/engineer-skills/groundwork-python-engineer/references/implementation-patterns.md +166 -0
- package/src/engineer-skills/groundwork-python-engineer/references/ml-pipelines.md +119 -0
- package/src/engineer-skills/groundwork-python-engineer/references/ml-systems-ai-engineering.md +74 -0
- package/src/engineer-skills/groundwork-python-engineer/references/observability.md +57 -0
- package/src/engineer-skills/groundwork-python-engineer/references/resilience.md +126 -0
- package/src/engineer-skills/groundwork-python-engineer/references/security.md +148 -0
- package/src/engineer-skills/groundwork-python-engineer/references/testing.md +216 -0
- package/src/engineer-skills/groundwork-python-engineer/sync-anchor.md +20 -0
- package/src/generators/add-capability/generator.ts +70 -0
- package/src/generators/add-capability/schema.json +30 -0
- package/src/generators/capabilities/llm/capability.json +28 -0
- package/src/generators/capabilities/llm/providers/anthropic/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/anthropic/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/anthropic/stacks/python/src/__packageName__/adapters/llm.py.template +61 -0
- package/src/generators/capabilities/llm/providers/local/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/local/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/local/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/localai/footprint.json +29 -0
- package/src/generators/capabilities/llm/providers/localai/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/localai/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/none/footprint.json +9 -0
- package/src/generators/capabilities/llm/providers/none/stacks/go/internal/llm/llm.go.template +35 -0
- package/src/generators/capabilities/llm/providers/none/stacks/python/src/__packageName__/adapters/llm.py.template +25 -0
- package/src/generators/capabilities/llm/providers/ollama/footprint.json +20 -0
- package/src/generators/capabilities/llm/providers/ollama/stacks/go/internal/llm/llm.go.template +102 -0
- package/src/generators/capabilities/llm/providers/ollama/stacks/python/src/__packageName__/adapters/llm.py.template +53 -0
- package/src/generators/capabilities/llm/providers/openai/footprint.json +13 -0
- package/src/generators/capabilities/llm/providers/openai/stacks/go/internal/llm/llm.go.template +98 -0
- package/src/generators/capabilities/llm/providers/openai/stacks/python/src/__packageName__/adapters/llm.py.template +60 -0
- package/src/generators/capabilities/llm/stacks/go/internal/core/service/llm.go.template +12 -0
- package/src/generators/capabilities/llm/stacks/go/internal/llm/llm_test.go.template +33 -0
- package/src/generators/capabilities/llm/stacks/python/src/__packageName__/core/llm.py.template +15 -0
- package/src/generators/capabilities/llm/stacks/python/tests/contracts/test_llm.py.template +37 -0
- package/src/generators/cli-app/files/README.md.template +76 -0
- package/src/generators/cli-app/files/build.mjs.template +15 -0
- package/src/generators/cli-app/files/package.json.template +21 -0
- package/src/generators/cli-app/files/src/cli.ts.template +67 -0
- package/src/generators/cli-app/files/src/commands/hello.ts.template +17 -0
- package/src/generators/cli-app/files/src/commands/status.ts.template +23 -0
- package/src/generators/cli-app/files/src/core/client.test.ts.template +80 -0
- package/src/generators/cli-app/files/src/core/client.ts.template +64 -0
- package/src/generators/cli-app/files/src/registry.test.ts.template +35 -0
- package/src/generators/cli-app/files/src/registry.ts.template +31 -0
- package/src/generators/cli-app/files/tsconfig.json.template +16 -0
- package/src/generators/cli-app/files/tsconfig.test.json.template +11 -0
- package/src/generators/cli-app/generator.ts +138 -0
- package/src/generators/cli-app/schema.json +24 -0
- package/src/generators/docs-site/files/.gitignore.ejs +40 -0
- package/src/generators/docs-site/files/app/docs/__slug__/page.tsx +101 -0
- package/src/generators/docs-site/files/app/docs/layout.tsx +14 -0
- package/src/generators/docs-site/files/app/docs.css +43 -0
- package/src/generators/docs-site/files/app/layout.tsx +24 -0
- package/src/generators/docs-site/files/app/page.tsx +135 -0
- package/src/generators/docs-site/files/app/source.ts +8 -0
- package/src/generators/docs-site/files/components/mermaid.tsx +67 -0
- package/src/generators/docs-site/files/next.config.mjs +10 -0
- package/src/generators/docs-site/files/package.json +32 -0
- package/src/generators/docs-site/files/pnpm-workspace.yaml +7 -0
- package/src/generators/docs-site/files/postcss.config.mjs +6 -0
- package/src/generators/docs-site/files/source.config.ts +77 -0
- package/src/generators/docs-site/files/tailwind.config.js +10 -0
- package/src/generators/docs-site/files/tsconfig.json +27 -0
- package/src/generators/docs-site/generator.ts +476 -0
- package/src/generators/docs-site/schema.json +17 -0
- package/src/generators/electron-app/docs/principles/stack/electron/index.md +49 -0
- package/src/generators/electron-app/docs/principles/stack/electron/ipc-contracts.md +71 -0
- package/src/generators/electron-app/docs/principles/stack/electron/packaging-and-updates.md +59 -0
- package/src/generators/electron-app/docs/principles/stack/electron/process-model.md +53 -0
- package/src/generators/electron-app/docs/principles/stack/electron/security.md +70 -0
- package/src/generators/electron-app/docs/principles/stack/typescript/frontend.md +65 -0
- package/src/generators/electron-app/files/.gitignore.template +20 -0
- package/src/generators/electron-app/files/README.md.template +125 -0
- package/src/generators/electron-app/files/electron.vite.config.ts +31 -0
- package/src/generators/electron-app/files/eslint.config.mjs +92 -0
- package/src/generators/electron-app/files/forge.config.ts.template +44 -0
- package/src/generators/electron-app/files/package.json.template +54 -0
- package/src/generators/electron-app/files/playwright.config.ts +18 -0
- package/src/generators/electron-app/files/project.json.template +65 -0
- package/src/generators/electron-app/files/src/main/core-client.test.ts +81 -0
- package/src/generators/electron-app/files/src/main/core-client.ts +55 -0
- package/src/generators/electron-app/files/src/main/index.ts +157 -0
- package/src/generators/electron-app/files/src/main/ipc.ts +52 -0
- package/src/generators/electron-app/files/src/main/policy.test.ts +71 -0
- package/src/generators/electron-app/files/src/main/policy.ts +73 -0
- package/src/generators/electron-app/files/src/preload/index.ts +23 -0
- package/src/generators/electron-app/files/src/renderer/index.html.template +20 -0
- package/src/generators/electron-app/files/src/renderer/src/App.test.tsx +61 -0
- package/src/generators/electron-app/files/src/renderer/src/App.tsx.template +43 -0
- package/src/generators/electron-app/files/src/renderer/src/assets/main.css +40 -0
- package/src/generators/electron-app/files/src/renderer/src/env.d.ts +14 -0
- package/src/generators/electron-app/files/src/renderer/src/main.tsx +25 -0
- package/src/generators/electron-app/files/src/shared/ipc.ts +54 -0
- package/src/generators/electron-app/files/tests/smoke/app.spec.ts.template +133 -0
- package/src/generators/electron-app/files/tool/electron_exec.sh.template +83 -0
- package/src/generators/electron-app/files/tsconfig.json +7 -0
- package/src/generators/electron-app/files/tsconfig.node.json +27 -0
- package/src/generators/electron-app/files/tsconfig.web.json +22 -0
- package/src/generators/electron-app/files/vitest.config.ts +32 -0
- package/src/generators/electron-app/files/vitest.setup.ts +1 -0
- package/src/generators/electron-app/generator.ts +288 -0
- package/src/generators/electron-app/schema.json +23 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/architecture.md +78 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/index.md +38 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/platform-channels.md +51 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/releases-and-distribution.md +59 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/state-management.md +85 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/testing.md +86 -0
- package/src/generators/flutter-app/docs/principles/stack/flutter/widgets-and-composition.md +69 -0
- package/src/generators/flutter-app/files/.gitignore.template +30 -0
- package/src/generators/flutter-app/files/README.md.template +100 -0
- package/src/generators/flutter-app/files/analysis_options.yaml.template +18 -0
- package/src/generators/flutter-app/files/integration_test/app_test.dart.template +64 -0
- package/src/generators/flutter-app/files/lib/app.dart.template +24 -0
- package/src/generators/flutter-app/files/lib/config/app_config.dart +15 -0
- package/src/generators/flutter-app/files/lib/data/repositories/status_repository.dart +36 -0
- package/src/generators/flutter-app/files/lib/data/services/api_client.dart +71 -0
- package/src/generators/flutter-app/files/lib/domain/models/health_status.dart +23 -0
- package/src/generators/flutter-app/files/lib/main.dart +11 -0
- package/src/generators/flutter-app/files/lib/router.dart +23 -0
- package/src/generators/flutter-app/files/lib/ui/core/theme/app_theme.dart +110 -0
- package/src/generators/flutter-app/files/lib/ui/home/home_view.dart +89 -0
- package/src/generators/flutter-app/files/lib/ui/home/home_view_model.dart.template +38 -0
- package/src/generators/flutter-app/files/project.json.template +51 -0
- package/src/generators/flutter-app/files/pubspec.yaml.template +47 -0
- package/src/generators/flutter-app/files/test/api_client_test.dart.template +63 -0
- package/src/generators/flutter-app/files/test/fakes/fake_status_repository.dart.template +19 -0
- package/src/generators/flutter-app/files/test/home_view_test.dart.template +58 -0
- package/src/generators/flutter-app/files/tool/flutter_exec.sh.template +60 -0
- package/src/generators/flutter-app/generator.ts +362 -0
- package/src/generators/flutter-app/schema.json +23 -0
- package/src/generators/go-microservice/docs/principles/stack/go/concurrency.md +123 -0
- package/src/generators/go-microservice/docs/principles/stack/go/index.md +70 -0
- package/src/generators/go-microservice/docs/principles/stack/go/testing.md +168 -0
- package/src/generators/go-microservice/files/.air.toml.template +38 -0
- package/src/generators/go-microservice/files/.env.template +4 -0
- package/src/generators/go-microservice/files/.golangci.yml.template +82 -0
- package/src/generators/go-microservice/files/Dockerfile.dev.template +12 -0
- package/src/generators/go-microservice/files/asyncapi-pubsub.yaml.template +33 -0
- package/src/generators/go-microservice/files/asyncapi-ws.yaml.template +34 -0
- package/src/generators/go-microservice/files/cmd/api/main.go.template +149 -0
- package/src/generators/go-microservice/files/cmd/api/main_test.go.template +99 -0
- package/src/generators/go-microservice/files/cmd/worker/cleanup/main.go.template +39 -0
- package/src/generators/go-microservice/files/db/schema.sql.template +24 -0
- package/src/generators/go-microservice/files/go.mod.template +39 -0
- package/src/generators/go-microservice/files/internal/config/config.go.template +52 -0
- package/src/generators/go-microservice/files/internal/config/otel.go.template +93 -0
- package/src/generators/go-microservice/files/internal/core/domain/errors.go.template +16 -0
- package/src/generators/go-microservice/files/internal/core/domain/model.go.template +28 -0
- package/src/generators/go-microservice/files/internal/core/domain/user.go.template +13 -0
- package/src/generators/go-microservice/files/internal/core/pagination.go.template +16 -0
- package/src/generators/go-microservice/files/internal/core/service/app_service.go.template +79 -0
- package/src/generators/go-microservice/files/internal/core/service/event_hub.go.template +9 -0
- package/src/generators/go-microservice/files/internal/core/service/message_queue.go.template +10 -0
- package/src/generators/go-microservice/files/internal/core/service/outbox_repository.go.template +31 -0
- package/src/generators/go-microservice/files/internal/core/service/repository.go.template +23 -0
- package/src/generators/go-microservice/files/internal/core/service/user_repository.go.template +15 -0
- package/src/generators/go-microservice/files/internal/core/service/user_service.go.template +43 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/app_handler.go.template +108 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/auth_middleware_test.go.template +52 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook.go.template +202 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/clerk_webhook_test.go.template +82 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/health_handler.go.template +80 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware.go.template +87 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/middleware_test.go.template +76 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/idempotency/repository.go.template +37 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_auth.go.template +40 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_loadshed.go.template +38 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_logging.go.template +40 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_ratelimit.go.template +48 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/middleware_test.go.template +81 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/router.go.template +105 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/types.go.template +70 -0
- package/src/generators/go-microservice/files/internal/entrypoints/api/websocket_handler.go.template +39 -0
- package/src/generators/go-microservice/files/internal/httpclient/http_client.go.template +87 -0
- package/src/generators/go-microservice/files/internal/kafka/kafka.go.template +34 -0
- package/src/generators/go-microservice/files/internal/postgres/postgres.go.template +195 -0
- package/src/generators/go-microservice/files/internal/postgres/postgres_test.go.template +156 -0
- package/src/generators/go-microservice/files/internal/postgres/user_repository.go.template +56 -0
- package/src/generators/go-microservice/files/internal/pubsub/gcp_pubsub.go.template +35 -0
- package/src/generators/go-microservice/files/internal/websocket/client.go.template +151 -0
- package/src/generators/go-microservice/files/internal/websocket/hub.go.template +261 -0
- package/src/generators/go-microservice/files/scripts/apply-schema.sh.template +21 -0
- package/src/generators/go-microservice/files/tools/tools.go.template +10 -0
- package/src/generators/go-microservice/generator.ts +240 -0
- package/src/generators/go-microservice/schema.json +63 -0
- package/src/generators/nextjs-app/docs/principles/stack/typescript/frontend.md +65 -0
- package/src/generators/nextjs-app/files/.dockerignore.template +7 -0
- package/src/generators/nextjs-app/files/.env.example.template +24 -0
- package/src/generators/nextjs-app/files/.gitignore.template +5 -0
- package/src/generators/nextjs-app/files/Dockerfile +53 -0
- package/src/generators/nextjs-app/files/app/(auth)/sign-in/__sign-in__/page.tsx.template +9 -0
- package/src/generators/nextjs-app/files/app/(auth)/sign-up/__sign-up__/page.tsx.template +9 -0
- package/src/generators/nextjs-app/files/app/api/config/route.ts.template +39 -0
- package/src/generators/nextjs-app/files/app/api/healthz/route.test.ts +15 -0
- package/src/generators/nextjs-app/files/app/api/healthz/route.ts +5 -0
- package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.test.ts.template +55 -0
- package/src/generators/nextjs-app/files/app/api/proxy/__path__/route.ts.template +126 -0
- package/src/generators/nextjs-app/files/app/error.tsx +39 -0
- package/src/generators/nextjs-app/files/app/global-error.tsx +68 -0
- package/src/generators/nextjs-app/files/app/globals.css +105 -0
- package/src/generators/nextjs-app/files/app/layout.tsx +59 -0
- package/src/generators/nextjs-app/files/app/loading.tsx +13 -0
- package/src/generators/nextjs-app/files/app/not-found.tsx +30 -0
- package/src/generators/nextjs-app/files/app/page.tsx +20 -0
- package/src/generators/nextjs-app/files/components/providers/default.tsx +19 -0
- package/src/generators/nextjs-app/files/components/providers/production.tsx +32 -0
- package/src/generators/nextjs-app/files/components/providers/telemetry.tsx +76 -0
- package/src/generators/nextjs-app/files/components/render-smoke.test.tsx +29 -0
- package/src/generators/nextjs-app/files/components/theme-provider.tsx +11 -0
- package/src/generators/nextjs-app/files/components.json +21 -0
- package/src/generators/nextjs-app/files/eslint.config.mjs +120 -0
- package/src/generators/nextjs-app/files/hooks/use-toast.ts +7 -0
- package/src/generators/nextjs-app/files/instrumentation.ts +90 -0
- package/src/generators/nextjs-app/files/lib/api/fetcher.ts.template +130 -0
- package/src/generators/nextjs-app/files/lib/config.ts +21 -0
- package/src/generators/nextjs-app/files/lib/logger.ts +29 -0
- package/src/generators/nextjs-app/files/lib/schemas/index.ts +19 -0
- package/src/generators/nextjs-app/files/lib/utils.ts +6 -0
- package/src/generators/nextjs-app/files/next.config.mjs +9 -0
- package/src/generators/nextjs-app/files/package.json +70 -0
- package/src/generators/nextjs-app/files/postcss.config.mjs +8 -0
- package/src/generators/nextjs-app/files/proxy.test.ts.template +30 -0
- package/src/generators/nextjs-app/files/proxy.ts +31 -0
- package/src/generators/nextjs-app/files/public/.gitkeep +1 -0
- package/src/generators/nextjs-app/files/tsconfig.json +42 -0
- package/src/generators/nextjs-app/files/vitest.config.mts +15 -0
- package/src/generators/nextjs-app/files/vitest.setup.ts +7 -0
- package/src/generators/nextjs-app/generator.ts +307 -0
- package/src/generators/nextjs-app/schema.json +44 -0
- package/src/generators/python-microservice/docs/principles/stack/python/async.md +168 -0
- package/src/generators/python-microservice/docs/principles/stack/python/documentation.md +240 -0
- package/src/generators/python-microservice/docs/principles/stack/python/mcp.md +147 -0
- package/src/generators/python-microservice/docs/principles/stack/python/resilience.md +193 -0
- package/src/generators/python-microservice/docs/principles/stack/python/testing.md +322 -0
- package/src/generators/python-microservice/files/.env.example.template +30 -0
- package/src/generators/python-microservice/files/Dockerfile.template +36 -0
- package/src/generators/python-microservice/files/db/schema.sql.template +19 -0
- package/src/generators/python-microservice/files/pyproject.toml.template +76 -0
- package/src/generators/python-microservice/files/scripts/apply-schema.sh.template +25 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/comfyui.py.template +87 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/config.py.template +48 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/database.py.template +21 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/message_queue.py.template +29 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/repository.py.template +130 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/telemetry.py.template +68 -0
- package/src/generators/python-microservice/files/src/__packageName__/adapters/websocket_hub.py.template +36 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/domain/entities.py.template +22 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/domain/exceptions.py.template +43 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/ports.py.template +42 -0
- package/src/generators/python-microservice/files/src/__packageName__/core/service/example_service.py.template +68 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/dependencies.py.template +50 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/middleware.py.template +131 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/router.py.template +37 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/api/websocket_handler.py.template +20 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/cleanup.py.template +35 -0
- package/src/generators/python-microservice/files/src/__packageName__/entrypoints/worker/worker.py.template +28 -0
- package/src/generators/python-microservice/files/src/__packageName__/main.py.template +108 -0
- package/src/generators/python-microservice/files/tests/test_main.py.template +74 -0
- package/src/generators/python-microservice/files/tests/test_middleware.py.template +109 -0
- package/src/generators/python-microservice/files/tests/test_worker.py.template +16 -0
- package/src/generators/python-microservice/generator.ts +286 -0
- package/src/generators/python-microservice/schema.json +86 -0
- package/src/generators/shared/brand-tokens.ts +301 -0
- package/src/generators/shared/capabilities.ts +349 -0
- package/src/generators/shared/provenance.ts +61 -0
- package/src/generators/shared/scaffold-helpers.ts +309 -0
- package/src/generators/system-test-runner/NATIVE-CHECK-CONTRACT.md +20 -0
- package/src/generators/system-test-runner/files/tests/bets/.gitkeep +0 -0
- package/src/generators/system-test-runner/files/tests/bets/_archive/.gitkeep +0 -0
- package/src/generators/system-test-runner/files/tests/conftest.py.template +503 -0
- package/src/generators/system-test-runner/files/tests/pyproject.toml.template +20 -0
- package/src/generators/system-test-runner/files/tests/system/pages/__init__.py.template +9 -0
- package/src/generators/system-test-runner/files/tests/system/pages/base_page.py.template +36 -0
- package/src/generators/system-test-runner/files/tests/system/test_a11y_smoke.py.template +132 -0
- package/src/generators/system-test-runner/files/tests/system/test_contract_conformance.py.template +140 -0
- package/src/generators/system-test-runner/files/tests/system/test_layout_geometry.py.template +109 -0
- package/src/generators/system-test-runner/files/tests/system/test_render_smoke.py.template +257 -0
- package/src/generators/system-test-runner/files/tests/system/test_system.py.template +158 -0
- package/src/generators/system-test-runner/files/tests/system/test_token_conformance.py.template +206 -0
- package/src/generators/system-test-runner/files/tests/system/test_visual_regression.py.template +104 -0
- package/src/generators/system-test-runner/generator.ts +196 -0
- package/src/generators/system-test-runner/schema.json +24 -0
- package/src/generators/workspace-dev-cli/cli-src/build.mjs +42 -0
- package/src/generators/workspace-dev-cli/cli-src/dist/dev-bundle.js +2168 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/bet.ts +442 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/completion.ts +87 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/doctor.ts +139 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/lifecycle.ts +548 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/quality.ts +127 -0
- package/src/generators/workspace-dev-cli/cli-src/src/commands/surface.ts +214 -0
- package/src/generators/workspace-dev-cli/cli-src/src/index.ts +127 -0
- package/src/generators/workspace-dev-cli/cli-src/src/registry.ts +194 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/color.ts +130 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/render.ts +158 -0
- package/src/generators/workspace-dev-cli/cli-src/src/theme/tokens.ts +122 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/context.ts +43 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/extensions.ts +99 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/paths.ts +46 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/proc.ts +106 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/prompt.ts +108 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/runners.ts +70 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/services.ts +221 -0
- package/src/generators/workspace-dev-cli/cli-src/src/util/version.ts +21 -0
- package/src/generators/workspace-dev-cli/cli-src/tsconfig.json +16 -0
- package/src/generators/workspace-dev-cli/files/.agents/skills/workspace-cli/SKILL.md.template +74 -0
- package/src/generators/workspace-dev-cli/files/dev.template +16 -0
- package/src/generators/workspace-dev-cli/files/docker-compose.yml.template +20 -0
- package/src/generators/workspace-dev-cli/files/scripts/cli/templates/milestone-test.pytmpl.template +46 -0
- package/src/generators/workspace-dev-cli/files/scripts/cli/templates/slice-test.pytmpl.template +38 -0
- package/src/generators/workspace-dev-cli/generator.ts +136 -0
- package/src/generators/workspace-dev-cli/schema.json +22 -0
- package/src/hidden-skills/code-intelligence.md +135 -0
- package/src/hidden-skills/groundwork-architect/SKILL.md +114 -0
- package/src/hidden-skills/groundwork-architect/references/agentic-systems.md +44 -0
- package/src/hidden-skills/groundwork-architect/references/ai-native-architecture.md +37 -0
- package/src/hidden-skills/groundwork-architect/references/api-and-contracts.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/core-and-boundaries.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/data-architecture.md +33 -0
- package/src/hidden-skills/groundwork-architect/references/decision-records.md +34 -0
- package/src/hidden-skills/groundwork-architect/references/durable-execution.md +45 -0
- package/src/hidden-skills/groundwork-architect/references/evolutionary-architecture.md +37 -0
- package/src/hidden-skills/groundwork-architect/references/identity-and-access.md +41 -0
- package/src/hidden-skills/groundwork-architect/references/integration-patterns.md +39 -0
- package/src/hidden-skills/groundwork-architect/references/observability.md +36 -0
- package/src/hidden-skills/groundwork-architect/references/performance-and-scale.md +41 -0
- package/src/hidden-skills/groundwork-architect/references/platform-and-delivery.md +47 -0
- package/src/hidden-skills/groundwork-architect/references/realtime-and-async.md +28 -0
- package/src/hidden-skills/groundwork-architect/references/reliability.md +31 -0
- package/src/hidden-skills/groundwork-architect/references/security-and-trust.md +47 -0
- package/src/hidden-skills/groundwork-architect/references/surface-architecture.md +40 -0
- package/src/hidden-skills/groundwork-architect/sync-anchor.md +34 -0
- package/src/hidden-skills/groundwork-architecture/architecture-template.md +50 -0
- package/src/hidden-skills/groundwork-architecture/instructions.md +139 -0
- package/src/hidden-skills/groundwork-architecture/phases/01-context-ingestion.md +18 -0
- package/src/hidden-skills/groundwork-architecture/phases/02-technical-constraints.md +27 -0
- package/src/hidden-skills/groundwork-architecture/phases/03-service-design.md +19 -0
- package/src/hidden-skills/groundwork-architecture/phases/04-data-flow-communication.md +23 -0
- package/src/hidden-skills/groundwork-architecture/phases/05-component-boundaries-contracts.md +17 -0
- package/src/hidden-skills/groundwork-architecture/phases/06-draft-review-present.md +38 -0
- package/src/hidden-skills/groundwork-architecture/phases/07-commit.md +33 -0
- package/src/hidden-skills/groundwork-architecture/templates/architecture-cache.md +43 -0
- package/src/hidden-skills/groundwork-architecture-extract/instructions.md +163 -0
- package/src/hidden-skills/groundwork-architecture-extract/templates/architecture-extract-cache.md +21 -0
- package/src/hidden-skills/groundwork-bet/briefs/acceptance-auditor.md +68 -0
- package/src/hidden-skills/groundwork-bet/briefs/blind-reviewer.md +56 -0
- package/src/hidden-skills/groundwork-bet/briefs/coverage-auditor.md +95 -0
- package/src/hidden-skills/groundwork-bet/briefs/edge-case-tracer.md +64 -0
- package/src/hidden-skills/groundwork-bet/briefs/experience-auditor.md +83 -0
- package/src/hidden-skills/groundwork-bet/briefs/slice-worker.md +257 -0
- package/src/hidden-skills/groundwork-bet/instructions.md +88 -0
- package/src/hidden-skills/groundwork-bet/templates/bet-progress-test.md +115 -0
- package/src/hidden-skills/groundwork-bet/templates/change-proposal.md +38 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/meta.json +4 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/milestone-index.md +31 -0
- package/src/hidden-skills/groundwork-bet/templates/decomposition/slice.md +31 -0
- package/src/hidden-skills/groundwork-bet/templates/pitch.md +45 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/01-ui-design.md +51 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/02-data-flows.md +36 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/03-api-design.md +90 -0
- package/src/hidden-skills/groundwork-bet/templates/technical-design/04-data-design.md +29 -0
- package/src/hidden-skills/groundwork-bet/workflows/01-discovery.md +200 -0
- package/src/hidden-skills/groundwork-bet/workflows/02-design.md +178 -0
- package/src/hidden-skills/groundwork-bet/workflows/03-decomposition.md +242 -0
- package/src/hidden-skills/groundwork-bet/workflows/04-delivery.md +226 -0
- package/src/hidden-skills/groundwork-bet/workflows/05-validation.md +210 -0
- package/src/hidden-skills/groundwork-design-system/instructions.md +125 -0
- package/src/hidden-skills/groundwork-design-system/templates/brand-tokens.md +182 -0
- package/src/hidden-skills/groundwork-design-system/templates/design-system-cache.md +64 -0
- package/src/hidden-skills/groundwork-design-system/tracks/_foundation.md +136 -0
- package/src/hidden-skills/groundwork-design-system/tracks/agentic-protocol.md +269 -0
- package/src/hidden-skills/groundwork-design-system/tracks/cli.md +355 -0
- package/src/hidden-skills/groundwork-design-system/tracks/graphical-ui.md +330 -0
- package/src/hidden-skills/groundwork-design-system-extract/instructions.md +124 -0
- package/src/hidden-skills/groundwork-design-system-extract/templates/design-system-extract-cache.md +19 -0
- package/src/hidden-skills/groundwork-designer/SKILL.md +108 -0
- package/src/hidden-skills/groundwork-designer/references/accessibility.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/ai-native-design.md +37 -0
- package/src/hidden-skills/groundwork-designer/references/design-review.md +29 -0
- package/src/hidden-skills/groundwork-designer/references/design-systems-and-tokens.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/interaction-and-motion.md +37 -0
- package/src/hidden-skills/groundwork-designer/references/layout-and-space.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/usability-and-ux.md +33 -0
- package/src/hidden-skills/groundwork-designer/references/visual-craft.md +49 -0
- package/src/hidden-skills/groundwork-designer/sync-anchor.md +20 -0
- package/src/hidden-skills/groundwork-doc-sync/instructions.md +100 -0
- package/src/hidden-skills/groundwork-elicit/instructions.md +66 -0
- package/src/hidden-skills/groundwork-elicit/methods.md +65 -0
- package/src/hidden-skills/groundwork-infra-adopt/instructions.md +168 -0
- package/src/hidden-skills/groundwork-infra-adopt/templates/infra-adopt-cache.md +21 -0
- package/src/hidden-skills/groundwork-mvp/instructions.md +223 -0
- package/src/hidden-skills/groundwork-mvp/templates/mvp-cache.md +9 -0
- package/src/hidden-skills/groundwork-patch/instructions.md +40 -0
- package/src/hidden-skills/groundwork-persona/instructions.md +65 -0
- package/src/hidden-skills/groundwork-product/SKILL.md +102 -0
- package/src/hidden-skills/groundwork-product/references/ai-native-product.md +45 -0
- package/src/hidden-skills/groundwork-product/references/discovery-and-opportunity.md +38 -0
- package/src/hidden-skills/groundwork-product/references/product-risks.md +52 -0
- package/src/hidden-skills/groundwork-product/references/requirements-and-specs.md +39 -0
- package/src/hidden-skills/groundwork-product/references/scope-and-sequencing.md +35 -0
- package/src/hidden-skills/groundwork-product/references/shaping-and-appetite.md +48 -0
- package/src/hidden-skills/groundwork-product/references/success-metrics-and-signals.md +37 -0
- package/src/hidden-skills/groundwork-product/sync-anchor.md +19 -0
- package/src/hidden-skills/groundwork-product-brief/instructions.md +231 -0
- package/src/hidden-skills/groundwork-product-brief-extract/instructions.md +139 -0
- package/src/hidden-skills/groundwork-product-brief-extract/templates/product-brief-extract-cache.md +17 -0
- package/src/hidden-skills/groundwork-review/checklists/architecture.md +93 -0
- package/src/hidden-skills/groundwork-review/checklists/bet-pitch.md +94 -0
- package/src/hidden-skills/groundwork-review/checklists/decomposition.md +135 -0
- package/src/hidden-skills/groundwork-review/checklists/design-system.md +85 -0
- package/src/hidden-skills/groundwork-review/checklists/domain-entity.md +66 -0
- package/src/hidden-skills/groundwork-review/checklists/implementation-readiness.md +47 -0
- package/src/hidden-skills/groundwork-review/checklists/infrastructure.md +68 -0
- package/src/hidden-skills/groundwork-review/checklists/maturity.md +71 -0
- package/src/hidden-skills/groundwork-review/checklists/product-brief.md +69 -0
- package/src/hidden-skills/groundwork-review/checklists/technical-design.md +112 -0
- package/src/hidden-skills/groundwork-review/instructions.md +181 -0
- package/src/hidden-skills/groundwork-scaffold/instructions.md +254 -0
- package/src/hidden-skills/groundwork-scaffold/phases/01-ingestion-service-mapping.md +87 -0
- package/src/hidden-skills/groundwork-scaffold/phases/02-scaffolding-execution.md +15 -0
- package/src/hidden-skills/groundwork-scaffold/phases/03-service-documentation-api-stubs.md +100 -0
- package/src/hidden-skills/groundwork-scaffold/phases/04-infrastructure-verification.md +17 -0
- package/src/hidden-skills/groundwork-scaffold/phases/05-draft-review.md +19 -0
- package/src/hidden-skills/groundwork-scaffold/phases/06-commit.md +19 -0
- package/src/hidden-skills/groundwork-scaffold/templates/scaffold-cache.md +23 -0
- package/src/hidden-skills/groundwork-scan/instructions.md +164 -0
- package/src/hidden-skills/groundwork-scan/references/digest-schema.md +66 -0
- package/src/hidden-skills/groundwork-scan/references/exclusions.md +44 -0
- package/src/hidden-skills/groundwork-scan/templates/architecture-findings.md +42 -0
- package/src/hidden-skills/groundwork-scan/templates/design-findings.md +23 -0
- package/src/hidden-skills/groundwork-scan/templates/overview.md +26 -0
- package/src/hidden-skills/groundwork-scan/templates/product-findings.md +23 -0
- package/src/hidden-skills/groundwork-scan/templates/scan-state.json +19 -0
- package/src/hidden-skills/groundwork-stack-forge/instructions.md +150 -0
- package/src/hidden-skills/groundwork-stack-forge/references/authoring-engineer-skills.md +107 -0
- package/src/hidden-skills/groundwork-surface-activation/instructions.md +138 -0
- package/src/hidden-skills/groundwork-update/briefs/reconcile-worker.md +196 -0
- package/src/hidden-skills/groundwork-update/instructions.md +200 -0
- package/src/hidden-skills/groundwork-writer/SKILL.md +278 -0
- package/src/hidden-skills/maturity-model.md +125 -0
- package/src/hidden-skills/operating-contract.md +400 -0
- package/src/hidden-skills/repo-map-schema.md +90 -0
- package/src/hidden-skills/templates/adr.md +57 -0
- package/src/hidden-skills/templates/capability-ports.md +71 -0
- package/src/hidden-skills/templates/discovery-notes.md +33 -0
- package/src/hidden-skills/templates/domain-entity.md +80 -0
- package/src/hidden-skills/templates/gap-ledger.md +21 -0
- package/src/hidden-skills/templates/handoff.md +37 -0
- package/src/hidden-skills/templates/maturity.md +39 -0
- package/src/hidden-skills/templates/surfaces.md +207 -0
- package/src/skills/groundwork-check/SKILL.md +56 -0
- package/src/skills/groundwork-check/instructions.md +70 -0
- package/src/skills/groundwork-orchestrator/SKILL.md +176 -0
- package/src/skills/groundwork-orchestrator/workflow-index.md +50 -0
package/src/engineer-skills/groundwork-nextjs-engineer/references/performance-and-deployment.md
ADDED
|
@@ -0,0 +1,947 @@
|
|
|
1
|
+
# Performance & Deployment
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [Image Optimisation](#image-optimisation)
|
|
5
|
+
- [Font Loading](#font-loading)
|
|
6
|
+
- [Bundling & Package Issues](#bundling--package-issues)
|
|
7
|
+
- [Third-Party Scripts](#third-party-scripts)
|
|
8
|
+
- [Metadata & SEO](#metadata--seo)
|
|
9
|
+
- [Self-Hosting](#self-hosting)
|
|
10
|
+
- [Docker Deployment](#docker-deployment)
|
|
11
|
+
- [ISR Cache Handlers](#isr-cache-handlers)
|
|
12
|
+
- [Debug Tools](#debug-tools)
|
|
13
|
+
- [Core Web Vitals](#core-web-vitals)
|
|
14
|
+
- [Serverless Deployment (OpenNext)](#serverless-deployment-opennext)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Image Optimisation
|
|
19
|
+
|
|
20
|
+
Always use `next/image`. Raw `<img>` tags bypass automatic optimisation, responsive sizing, and lazy loading.
|
|
21
|
+
|
|
22
|
+
### Local Images
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
import meetingHero from '@/public/meeting-hero.webp';
|
|
26
|
+
import Image from 'next/image';
|
|
27
|
+
|
|
28
|
+
// Width and height are auto-inferred from the import
|
|
29
|
+
<Image
|
|
30
|
+
src={meetingHero}
|
|
31
|
+
alt="Meeting room with glass walls"
|
|
32
|
+
placeholder="blur" // Auto-generates blur placeholder from static import
|
|
33
|
+
priority // Set for LCP (Largest Contentful Paint) images
|
|
34
|
+
/>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Remote Images
|
|
38
|
+
|
|
39
|
+
Remote images require explicit dimensions and a configured `remotePatterns` in `next.config.ts`:
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
// next.config.ts
|
|
43
|
+
const nextConfig = {
|
|
44
|
+
images: {
|
|
45
|
+
remotePatterns: [
|
|
46
|
+
{
|
|
47
|
+
protocol: 'https',
|
|
48
|
+
hostname: 'api.example.com',
|
|
49
|
+
pathname: '/v1/media/**',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
protocol: 'https',
|
|
53
|
+
hostname: 'avatars.githubusercontent.com',
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
<Image
|
|
62
|
+
src={`https://api.example.com/v1/media/${imageId}`}
|
|
63
|
+
alt={imageAlt}
|
|
64
|
+
width={800}
|
|
65
|
+
height={450}
|
|
66
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
67
|
+
/>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Responsive Images
|
|
71
|
+
|
|
72
|
+
Use the `sizes` prop to tell the browser how wide the image will be at each viewport:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
// Full width on mobile, half on tablet, third on desktop
|
|
76
|
+
<Image
|
|
77
|
+
src={src}
|
|
78
|
+
alt={alt}
|
|
79
|
+
fill // Fills parent container
|
|
80
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
81
|
+
className="object-cover" // CSS controls positioning within the container
|
|
82
|
+
/>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Priority Loading
|
|
86
|
+
|
|
87
|
+
Set `priority` on the **Largest Contentful Paint** image — typically the hero image or primary visual above the fold. Only one image per page should have `priority`.
|
|
88
|
+
|
|
89
|
+
### Common Mistakes
|
|
90
|
+
|
|
91
|
+
| Mistake | Fix |
|
|
92
|
+
|---------|-----|
|
|
93
|
+
| Using `<img>` tags | Always `next/image` |
|
|
94
|
+
| Missing `alt` text | Always provide descriptive alt text |
|
|
95
|
+
| Missing `sizes` with `fill` | Always specify how wide the image renders at each breakpoint |
|
|
96
|
+
| `priority` on multiple images | Only the LCP image gets `priority` |
|
|
97
|
+
| Remote images without `remotePatterns` | Configure in `next.config.ts` |
|
|
98
|
+
|
|
99
|
+
### Image Optimisation Tuning
|
|
100
|
+
|
|
101
|
+
For self-hosted deployments, reduce CPU load by limiting generated variants and extending cache TTL:
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
// next.config.ts
|
|
105
|
+
const nextConfig = {
|
|
106
|
+
images: {
|
|
107
|
+
minimumCacheTTL: 60 * 60 * 24, // 24 hours
|
|
108
|
+
deviceSizes: [640, 750, 1080, 1920], // Limit generated sizes
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
For high-traffic sites, offload image optimisation to Cloudinary, Imgix, or a similar CDN:
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
// next.config.ts
|
|
117
|
+
const nextConfig = {
|
|
118
|
+
images: {
|
|
119
|
+
loader: 'custom',
|
|
120
|
+
loaderFile: './lib/image-loader.ts',
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```tsx
|
|
126
|
+
// lib/image-loader.ts
|
|
127
|
+
export default function cloudinaryLoader({
|
|
128
|
+
src, width, quality,
|
|
129
|
+
}: { src: string; width: number; quality?: number }) {
|
|
130
|
+
const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality ?? 'auto'}`];
|
|
131
|
+
return `https://res.cloudinary.com/example/image/upload/${params.join(',')}${src}`;
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Static Export
|
|
136
|
+
|
|
137
|
+
When using `output: 'export'` for a fully static site, image optimisation is disabled. Use `unoptimized` or a custom loader:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
// next.config.ts — disable optimisation globally
|
|
141
|
+
const nextConfig = {
|
|
142
|
+
output: 'export',
|
|
143
|
+
images: { unoptimized: true },
|
|
144
|
+
};
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
// Or per-image
|
|
149
|
+
<Image src="/hero.png" alt="Hero" width={800} height={400} unoptimized />
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## Font Loading
|
|
155
|
+
|
|
156
|
+
Use `next/font` to load all typefaces. Never use `<link>` tags or CSS `@import` for fonts — these block rendering and create layout shifts.
|
|
157
|
+
|
|
158
|
+
### Geist Setup
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
// lib/fonts.ts — shared font definitions
|
|
162
|
+
import { GeistSans } from 'geist/font/sans';
|
|
163
|
+
import { GeistMono } from 'geist/font/mono';
|
|
164
|
+
|
|
165
|
+
export const fontSans = GeistSans;
|
|
166
|
+
export const fontMono = GeistMono;
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
```tsx
|
|
170
|
+
// app/layout.tsx
|
|
171
|
+
import { fontSans, fontMono } from '@/lib/fonts';
|
|
172
|
+
|
|
173
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
174
|
+
return (
|
|
175
|
+
<html
|
|
176
|
+
lang="en"
|
|
177
|
+
className={`${fontSans.variable} ${fontMono.variable}`}
|
|
178
|
+
>
|
|
179
|
+
<body className="font-sans">
|
|
180
|
+
{children}
|
|
181
|
+
</body>
|
|
182
|
+
</html>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Integration with Tailwind
|
|
188
|
+
|
|
189
|
+
The CSS variables are referenced in `@theme`:
|
|
190
|
+
|
|
191
|
+
```css
|
|
192
|
+
@theme {
|
|
193
|
+
--font-sans: 'Geist', sans-serif;
|
|
194
|
+
--font-mono: 'Geist Mono', monospace;
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Rules
|
|
199
|
+
|
|
200
|
+
- **One font file**, shared everywhere — define in `lib/fonts.ts`, import in root layout
|
|
201
|
+
- **Never import per-component** — fonts imported in multiple components create duplicate download requests
|
|
202
|
+
- **Never use `@import url('fonts.googleapis.com/...')`** in CSS — blocks rendering
|
|
203
|
+
- **Subset to `latin`** unless the app requires other character sets
|
|
204
|
+
- **Use `display: 'swap'`** (default in next/font) — shows fallback font immediately, swaps when loaded
|
|
205
|
+
|
|
206
|
+
### Font Weight Selection
|
|
207
|
+
|
|
208
|
+
Geist is a variable font — it includes all weights automatically. For non-variable fonts, specify only the weights you use:
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
// Variable font (recommended) — all weights included
|
|
212
|
+
import { Inter } from 'next/font/google';
|
|
213
|
+
const inter = Inter({ subsets: ['latin'] });
|
|
214
|
+
|
|
215
|
+
// Non-variable font — specify only needed weights
|
|
216
|
+
import { Roboto } from 'next/font/google';
|
|
217
|
+
const roboto = Roboto({
|
|
218
|
+
subsets: ['latin'],
|
|
219
|
+
weight: ['400', '500', '700'],
|
|
220
|
+
});
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Local Fonts
|
|
224
|
+
|
|
225
|
+
For custom or licensed fonts not available on Google Fonts:
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
import localFont from 'next/font/local';
|
|
229
|
+
|
|
230
|
+
const customFont = localFont({
|
|
231
|
+
src: [
|
|
232
|
+
{ path: './fonts/Custom-Regular.woff2', weight: '400', style: 'normal' },
|
|
233
|
+
{ path: './fonts/Custom-Bold.woff2', weight: '700', style: 'normal' },
|
|
234
|
+
],
|
|
235
|
+
variable: '--font-custom',
|
|
236
|
+
});
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Display Strategy Options
|
|
240
|
+
|
|
241
|
+
| Value | Behaviour | Use When |
|
|
242
|
+
|-------|-----------|----------|
|
|
243
|
+
| `'swap'` | Show fallback immediately, swap when font loads | Default — best for most cases |
|
|
244
|
+
| `'block'` | Short invisible period, then swap | Font is critical to brand identity |
|
|
245
|
+
| `'fallback'` | Short invisible, short swap window, then fallback | Acceptable if custom font doesn't load |
|
|
246
|
+
| `'optional'` | Short invisible, no swap | Font is decorative, not essential |
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Bundling & Package Issues
|
|
251
|
+
|
|
252
|
+
### Server-Incompatible Packages
|
|
253
|
+
|
|
254
|
+
Some npm packages reference `window`, `document`, or other browser APIs. These crash when imported in Server Components.
|
|
255
|
+
|
|
256
|
+
### Error Signs
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
ReferenceError: window is not defined
|
|
260
|
+
ReferenceError: document is not defined
|
|
261
|
+
ReferenceError: localStorage is not defined
|
|
262
|
+
Module not found: Can't resolve 'fs'
|
|
263
|
+
SyntaxError: Cannot use import statement outside a module
|
|
264
|
+
Error: require() of ES Module
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
#### Fix 1: Dynamic Import with ssr: false
|
|
268
|
+
|
|
269
|
+
```tsx
|
|
270
|
+
import dynamic from 'next/dynamic';
|
|
271
|
+
|
|
272
|
+
const RichTextEditor = dynamic(
|
|
273
|
+
() => import('@/components/rich-text-editor'),
|
|
274
|
+
{ ssr: false, loading: () => <EditorSkeleton /> }
|
|
275
|
+
);
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
#### Fix 2: serverExternalPackages
|
|
279
|
+
|
|
280
|
+
For packages that should run on the server but fail due to ESM/CJS issues:
|
|
281
|
+
|
|
282
|
+
```tsx
|
|
283
|
+
// next.config.ts
|
|
284
|
+
const nextConfig = {
|
|
285
|
+
serverExternalPackages: ['sharp', 'canvas'],
|
|
286
|
+
};
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
#### Fix 3: Client Wrapper
|
|
290
|
+
|
|
291
|
+
Wrap the problematic import behind a `"use client"` boundary:
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
// components/chart-wrapper.tsx
|
|
295
|
+
'use client';
|
|
296
|
+
|
|
297
|
+
import { ResponsiveChart } from 'some-chart-library';
|
|
298
|
+
export { ResponsiveChart };
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### ESM/CJS Resolution
|
|
302
|
+
|
|
303
|
+
For packages that ship ESM but aren't properly resolved:
|
|
304
|
+
|
|
305
|
+
```tsx
|
|
306
|
+
// next.config.ts
|
|
307
|
+
const nextConfig = {
|
|
308
|
+
transpilePackages: ['package-name'],
|
|
309
|
+
};
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### CSS Imports
|
|
313
|
+
|
|
314
|
+
Import CSS from npm packages using `import`, not `<link>`:
|
|
315
|
+
|
|
316
|
+
```tsx
|
|
317
|
+
// Good — in a client component or layout
|
|
318
|
+
import 'some-package/dist/styles.css';
|
|
319
|
+
|
|
320
|
+
// Bad — in <head> via <link>
|
|
321
|
+
<link rel="stylesheet" href="/node_modules/some-package/dist/styles.css" />
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### Bundle Analysis
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
pnpm dlx @next/bundle-analyzer
|
|
328
|
+
ANALYZE=true pnpm build
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Generates an interactive treemap showing what contributes most to bundle size. Look for:
|
|
332
|
+
- Duplicate dependencies
|
|
333
|
+
- Large unused libraries
|
|
334
|
+
- Server-only code leaking to the client bundle
|
|
335
|
+
|
|
336
|
+
### Polyfills
|
|
337
|
+
|
|
338
|
+
Next.js includes common polyfills automatically (`Array.from`, `Object.assign`, `Promise`, `fetch`, `Map`, `Set`, `Symbol`, `URLSearchParams`, and 50+ others). Do not load redundant polyfills from CDNs.
|
|
339
|
+
|
|
340
|
+
### Common Problematic Packages
|
|
341
|
+
|
|
342
|
+
| Package | Issue | Fix |
|
|
343
|
+
|---------|-------|-----|
|
|
344
|
+
| `sharp` | Native bindings | `serverExternalPackages: ['sharp']` |
|
|
345
|
+
| `bcrypt` | Native bindings | `serverExternalPackages: ['bcrypt']` or use `bcryptjs` |
|
|
346
|
+
| `canvas` | Native bindings | `serverExternalPackages: ['canvas']` |
|
|
347
|
+
| `recharts` | Uses `window` | `dynamic(() => import('recharts'), { ssr: false })` |
|
|
348
|
+
| `react-quill` | Uses `document` | `dynamic(() => import('react-quill'), { ssr: false })` |
|
|
349
|
+
| `mapbox-gl` | Uses `window` | `dynamic(() => import('mapbox-gl'), { ssr: false })` |
|
|
350
|
+
| `monaco-editor` | Uses `window` | `dynamic(() => import('@monaco-editor/react'), { ssr: false })` |
|
|
351
|
+
| `lottie-web` | Uses `document` | `dynamic(() => import('lottie-react'), { ssr: false })` |
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
## Third-Party Scripts
|
|
356
|
+
|
|
357
|
+
Use `next/script` for all external scripts. Never use raw `<script>` tags.
|
|
358
|
+
|
|
359
|
+
```tsx
|
|
360
|
+
import Script from 'next/script';
|
|
361
|
+
|
|
362
|
+
<Script
|
|
363
|
+
src="https://analytics.example.com/script.js"
|
|
364
|
+
strategy="afterInteractive" // Load after page becomes interactive
|
|
365
|
+
id="analytics" // Required for inline scripts
|
|
366
|
+
/>
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Loading Strategies
|
|
370
|
+
|
|
371
|
+
| Strategy | When It Loads | Use For |
|
|
372
|
+
|----------|--------------|---------|
|
|
373
|
+
| `afterInteractive` | After hydration | Analytics, chat widgets |
|
|
374
|
+
| `lazyOnload` | During idle time | Non-critical features, social embeds |
|
|
375
|
+
| `beforeInteractive` | Before hydration | Critical polyfills, consent managers |
|
|
376
|
+
| `worker` | Web Worker (experimental) | Heavy computation scripts |
|
|
377
|
+
|
|
378
|
+
### Google Analytics
|
|
379
|
+
|
|
380
|
+
```tsx
|
|
381
|
+
import { GoogleAnalytics } from '@next/third-parties/google';
|
|
382
|
+
|
|
383
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
384
|
+
return (
|
|
385
|
+
<html>
|
|
386
|
+
<body>
|
|
387
|
+
{children}
|
|
388
|
+
<GoogleAnalytics gaId="G-XXXXXXXXXX" />
|
|
389
|
+
</body>
|
|
390
|
+
</html>
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
### Google Tag Manager
|
|
396
|
+
|
|
397
|
+
```tsx
|
|
398
|
+
import { GoogleTagManager } from '@next/third-parties/google';
|
|
399
|
+
|
|
400
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
401
|
+
return (
|
|
402
|
+
<html>
|
|
403
|
+
<GoogleTagManager gtmId="GTM-XXXXXXXXX" />
|
|
404
|
+
<body>{children}</body>
|
|
405
|
+
</html>
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Third-Party Embeds
|
|
411
|
+
|
|
412
|
+
```tsx
|
|
413
|
+
import { YouTubeEmbed, GoogleMapsEmbed } from '@next/third-parties/google';
|
|
414
|
+
|
|
415
|
+
// YouTube — lazy-loaded, privacy-enhanced
|
|
416
|
+
<YouTubeEmbed videoid="dQw4w9WgXcQ" />
|
|
417
|
+
|
|
418
|
+
// Google Maps
|
|
419
|
+
<GoogleMapsEmbed
|
|
420
|
+
apiKey={process.env.NEXT_PUBLIC_MAPS_KEY!}
|
|
421
|
+
mode="place"
|
|
422
|
+
q="Brooklyn+Bridge,New+York,NY"
|
|
423
|
+
/>
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Rules
|
|
427
|
+
|
|
428
|
+
- All `<Script>` components must have an `id` if they contain inline code
|
|
429
|
+
- Never place `<Script>` inside `<Head>` — it belongs in the component body
|
|
430
|
+
- Use `@next/third-parties` for Google services (Analytics, GTM, Maps, YouTube)
|
|
431
|
+
- `strategy="beforeInteractive"` only works in the root `app/layout.tsx`
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## Metadata & SEO
|
|
436
|
+
|
|
437
|
+
The `metadata` object and `generateMetadata` function are **only supported in Server Components**. They cannot be used in files with `'use client'`. If a page needs both client interactivity and metadata:
|
|
438
|
+
1. Remove `'use client'` and move client logic to child components
|
|
439
|
+
2. Or extract metadata to a parent Server Component layout
|
|
440
|
+
3. Or split the file: Server Component with metadata imports Client Components
|
|
441
|
+
|
|
442
|
+
### Deduplicating Metadata Fetches
|
|
443
|
+
|
|
444
|
+
When `generateMetadata` and the page component need the same data, use `React.cache()` to deduplicate:
|
|
445
|
+
|
|
446
|
+
```tsx
|
|
447
|
+
import { cache } from 'react';
|
|
448
|
+
|
|
449
|
+
const getMeeting = cache(async (id: string) => {
|
|
450
|
+
return await fetchMeetingFromApi(id);
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
// generateMetadata and the page both call getMeeting(id)
|
|
454
|
+
// React.cache ensures only one API request is made
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Static Metadata
|
|
458
|
+
|
|
459
|
+
```tsx
|
|
460
|
+
// app/layout.tsx
|
|
461
|
+
import type { Metadata } from 'next';
|
|
462
|
+
|
|
463
|
+
export const metadata: Metadata = {
|
|
464
|
+
title: {
|
|
465
|
+
default: 'Example App',
|
|
466
|
+
template: '%s | Example App', // Child pages: "Meetings | Example App"
|
|
467
|
+
},
|
|
468
|
+
description: 'Meeting management for modern teams',
|
|
469
|
+
};
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
### Dynamic Metadata
|
|
473
|
+
|
|
474
|
+
```tsx
|
|
475
|
+
// app/meetings/[id]/page.tsx
|
|
476
|
+
import type { Metadata } from 'next';
|
|
477
|
+
import { getMeeting } from '@/lib/api';
|
|
478
|
+
|
|
479
|
+
type Props = { params: Promise<{ id: string }> };
|
|
480
|
+
|
|
481
|
+
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
|
482
|
+
const { id } = await params;
|
|
483
|
+
const meeting = await getMeeting(id);
|
|
484
|
+
|
|
485
|
+
return {
|
|
486
|
+
title: meeting.title,
|
|
487
|
+
description: `Meeting details: ${meeting.title}`,
|
|
488
|
+
openGraph: {
|
|
489
|
+
title: meeting.title,
|
|
490
|
+
type: 'article',
|
|
491
|
+
},
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Viewport (Separate Export)
|
|
497
|
+
|
|
498
|
+
Viewport configuration must be a separate export — not part of `metadata`:
|
|
499
|
+
|
|
500
|
+
```tsx
|
|
501
|
+
import type { Viewport } from 'next';
|
|
502
|
+
|
|
503
|
+
export const viewport: Viewport = {
|
|
504
|
+
themeColor: [
|
|
505
|
+
{ media: '(prefers-color-scheme: light)', color: '#f8f8f8' },
|
|
506
|
+
{ media: '(prefers-color-scheme: dark)', color: '#1a1a1a' },
|
|
507
|
+
],
|
|
508
|
+
width: 'device-width',
|
|
509
|
+
initialScale: 1,
|
|
510
|
+
};
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
For dynamic viewport configuration, use `generateViewport`:
|
|
514
|
+
|
|
515
|
+
```tsx
|
|
516
|
+
import type { Viewport } from 'next';
|
|
517
|
+
|
|
518
|
+
export function generateViewport({ params }: Props): Viewport {
|
|
519
|
+
return {
|
|
520
|
+
themeColor: getThemeColor(params),
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### File-Based Metadata
|
|
526
|
+
|
|
527
|
+
| File | Purpose |
|
|
528
|
+
|------|---------|
|
|
529
|
+
| `app/favicon.ico` | Browser tab icon |
|
|
530
|
+
| `app/icon.tsx` | Generated app icon |
|
|
531
|
+
| `app/apple-icon.tsx` | Apple touch icon |
|
|
532
|
+
| `app/opengraph-image.tsx` | OG image (generated) |
|
|
533
|
+
| `app/sitemap.ts` | XML sitemap |
|
|
534
|
+
| `app/robots.ts` | Robots.txt |
|
|
535
|
+
| `app/manifest.ts` | Web app manifest |
|
|
536
|
+
|
|
537
|
+
### OG Image Generation
|
|
538
|
+
|
|
539
|
+
Use `next/og` (not `@vercel/og`) to generate Open Graph images at build time:
|
|
540
|
+
|
|
541
|
+
```tsx
|
|
542
|
+
// app/opengraph-image.tsx
|
|
543
|
+
import { ImageResponse } from 'next/og';
|
|
544
|
+
|
|
545
|
+
export const runtime = 'edge';
|
|
546
|
+
export const size = { width: 1200, height: 630 };
|
|
547
|
+
export const contentType = 'image/png';
|
|
548
|
+
|
|
549
|
+
export default function OGImage() {
|
|
550
|
+
return new ImageResponse(
|
|
551
|
+
(
|
|
552
|
+
<div style={{
|
|
553
|
+
display: 'flex',
|
|
554
|
+
alignItems: 'center',
|
|
555
|
+
justifyContent: 'center',
|
|
556
|
+
width: '100%',
|
|
557
|
+
height: '100%',
|
|
558
|
+
background: 'linear-gradient(135deg, #1a1a2e 0%, #16213e 100%)',
|
|
559
|
+
color: 'white',
|
|
560
|
+
fontSize: 64,
|
|
561
|
+
fontWeight: 700,
|
|
562
|
+
}}>
|
|
563
|
+
Example App
|
|
564
|
+
</div>
|
|
565
|
+
),
|
|
566
|
+
{ ...size }
|
|
567
|
+
);
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
**Styling constraints:** ImageResponse uses Flexbox layout only — no CSS Grid. All styles must be inline objects.
|
|
572
|
+
|
|
573
|
+
### Custom Fonts in OG Images
|
|
574
|
+
|
|
575
|
+
```tsx
|
|
576
|
+
import { ImageResponse } from 'next/og';
|
|
577
|
+
import { readFile } from 'fs/promises';
|
|
578
|
+
import { join } from 'path';
|
|
579
|
+
|
|
580
|
+
export default async function OGImage() {
|
|
581
|
+
const fontPath = join(process.cwd(), 'assets/fonts/Geist-Bold.ttf');
|
|
582
|
+
const fontData = await readFile(fontPath);
|
|
583
|
+
|
|
584
|
+
return new ImageResponse(
|
|
585
|
+
(<div style={{ fontFamily: 'Geist', fontSize: 64 }}>Example App</div>),
|
|
586
|
+
{
|
|
587
|
+
width: 1200,
|
|
588
|
+
height: 630,
|
|
589
|
+
fonts: [{ name: 'Geist', data: fontData, style: 'normal' }],
|
|
590
|
+
}
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
### Multiple OG Images per Route
|
|
596
|
+
|
|
597
|
+
Use `generateImageMetadata` when a route needs multiple OG images:
|
|
598
|
+
|
|
599
|
+
```tsx
|
|
600
|
+
// app/meetings/[id]/opengraph-image.tsx
|
|
601
|
+
import { ImageResponse } from 'next/og';
|
|
602
|
+
|
|
603
|
+
export async function generateImageMetadata({ params }: Props) {
|
|
604
|
+
const images = await getMeetingImages(params.id);
|
|
605
|
+
return images.map((img, idx) => ({
|
|
606
|
+
id: idx,
|
|
607
|
+
alt: img.alt,
|
|
608
|
+
size: { width: 1200, height: 630 },
|
|
609
|
+
contentType: 'image/png' as const,
|
|
610
|
+
}));
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
export default async function OGImage({ params, id }: { params: Props['params']; id: number }) {
|
|
614
|
+
const images = await getMeetingImages(params.id);
|
|
615
|
+
const image = images[id];
|
|
616
|
+
return new ImageResponse(/* render image */);
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
### Multiple Sitemaps
|
|
621
|
+
|
|
622
|
+
Use `generateSitemaps` for large sites with over 50,000 URLs:
|
|
623
|
+
|
|
624
|
+
```tsx
|
|
625
|
+
// app/sitemap.ts
|
|
626
|
+
import type { MetadataRoute } from 'next';
|
|
627
|
+
|
|
628
|
+
export async function generateSitemaps() {
|
|
629
|
+
return [{ id: 0 }, { id: 1 }, { id: 2 }];
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
export default async function sitemap({
|
|
633
|
+
id,
|
|
634
|
+
}: { id: number }): Promise<MetadataRoute.Sitemap> {
|
|
635
|
+
const start = id * 50000;
|
|
636
|
+
const end = start + 50000;
|
|
637
|
+
const meetings = await getMeetings(start, end);
|
|
638
|
+
|
|
639
|
+
return meetings.map(meeting => ({
|
|
640
|
+
url: `https://example.com/meetings/${meeting.id}`,
|
|
641
|
+
lastModified: meeting.updated_at,
|
|
642
|
+
}));
|
|
643
|
+
}
|
|
644
|
+
```
|
|
645
|
+
|
|
646
|
+
Generates `/sitemap/0.xml`, `/sitemap/1.xml`, etc.
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
## Self-Hosting
|
|
651
|
+
|
|
652
|
+
### Standalone Output
|
|
653
|
+
|
|
654
|
+
Configure Next.js to produce a minimal standalone build that includes only the files needed to run:
|
|
655
|
+
|
|
656
|
+
```tsx
|
|
657
|
+
// next.config.ts
|
|
658
|
+
const nextConfig = {
|
|
659
|
+
output: 'standalone',
|
|
660
|
+
};
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
This creates `.next/standalone/` with a self-contained Node.js server.
|
|
664
|
+
|
|
665
|
+
### Health Check Endpoint
|
|
666
|
+
|
|
667
|
+
```tsx
|
|
668
|
+
// app/api/health/route.ts
|
|
669
|
+
export async function GET() {
|
|
670
|
+
return Response.json({ status: 'ok' }, { status: 200 });
|
|
671
|
+
}
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
### Environment Variables
|
|
675
|
+
|
|
676
|
+
| Type | Prefix | Available | Use For |
|
|
677
|
+
|------|--------|-----------|---------|
|
|
678
|
+
| Server-only | None | Server only | Database URLs, API keys, secrets |
|
|
679
|
+
| Public | `NEXT_PUBLIC_` | Server + client | API base URLs, feature flags |
|
|
680
|
+
|
|
681
|
+
```env
|
|
682
|
+
# Server-only
|
|
683
|
+
DATABASE_URL=postgres://...
|
|
684
|
+
API_SECRET_KEY=sk-xxx
|
|
685
|
+
|
|
686
|
+
# Public — embedded in client bundle
|
|
687
|
+
NEXT_PUBLIC_API_URL=https://api.example.com
|
|
688
|
+
NEXT_PUBLIC_POSTHOG_KEY=phc_xxx
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
---
|
|
692
|
+
|
|
693
|
+
## Docker Deployment
|
|
694
|
+
|
|
695
|
+
### Multi-Stage Dockerfile
|
|
696
|
+
|
|
697
|
+
```dockerfile
|
|
698
|
+
# Stage 1: Dependencies
|
|
699
|
+
FROM node:22-alpine AS deps
|
|
700
|
+
RUN corepack enable && corepack prepare pnpm@latest --activate
|
|
701
|
+
WORKDIR /app
|
|
702
|
+
COPY package.json pnpm-lock.yaml ./
|
|
703
|
+
RUN pnpm install --frozen-lockfile
|
|
704
|
+
|
|
705
|
+
# Stage 2: Build
|
|
706
|
+
FROM node:22-alpine AS builder
|
|
707
|
+
RUN corepack enable && corepack prepare pnpm@latest --activate
|
|
708
|
+
WORKDIR /app
|
|
709
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
710
|
+
COPY . .
|
|
711
|
+
RUN pnpm build
|
|
712
|
+
|
|
713
|
+
# Stage 3: Production
|
|
714
|
+
FROM node:22-alpine AS runner
|
|
715
|
+
WORKDIR /app
|
|
716
|
+
ENV NODE_ENV=production
|
|
717
|
+
|
|
718
|
+
# Create non-root user for security
|
|
719
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
720
|
+
RUN adduser --system --uid 1001 nextjs
|
|
721
|
+
|
|
722
|
+
# Copy standalone output
|
|
723
|
+
COPY --from=builder /app/.next/standalone ./
|
|
724
|
+
COPY --from=builder /app/.next/static ./.next/static
|
|
725
|
+
COPY --from=builder /app/public ./public
|
|
726
|
+
|
|
727
|
+
USER nextjs
|
|
728
|
+
|
|
729
|
+
EXPOSE 3000
|
|
730
|
+
ENV PORT=3000
|
|
731
|
+
ENV HOSTNAME="0.0.0.0"
|
|
732
|
+
|
|
733
|
+
CMD ["node", "server.js"]
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### Docker Compose
|
|
737
|
+
|
|
738
|
+
```yaml
|
|
739
|
+
services:
|
|
740
|
+
app:
|
|
741
|
+
build: .
|
|
742
|
+
ports:
|
|
743
|
+
- "3000:3000"
|
|
744
|
+
environment:
|
|
745
|
+
- NEXT_PUBLIC_API_URL=https://api.example.com
|
|
746
|
+
healthcheck:
|
|
747
|
+
test: ["CMD", "wget", "--spider", "-q", "http://localhost:3000/api/health"]
|
|
748
|
+
interval: 30s
|
|
749
|
+
timeout: 10s
|
|
750
|
+
retries: 3
|
|
751
|
+
start_period: 10s
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
## ISR Cache Handlers
|
|
757
|
+
|
|
758
|
+
When self-hosting with multiple instances, ISR (Incremental Static Regeneration) needs a shared cache backend. By default, the ISR cache is stored on the local filesystem, which doesn't work across multiple servers.
|
|
759
|
+
|
|
760
|
+
### Redis Cache Handler
|
|
761
|
+
|
|
762
|
+
```tsx
|
|
763
|
+
// cache-handler.mjs
|
|
764
|
+
import { CacheHandler } from '@neshca/cache-handler';
|
|
765
|
+
import createRedisHandler from '@neshca/cache-handler/redis-strings';
|
|
766
|
+
import { createClient } from 'redis';
|
|
767
|
+
|
|
768
|
+
CacheHandler.onCreation(async () => {
|
|
769
|
+
const client = createClient({ url: process.env.REDIS_URL });
|
|
770
|
+
await client.connect();
|
|
771
|
+
|
|
772
|
+
const handler = await createRedisHandler({ client, keyPrefix: 'next:' });
|
|
773
|
+
|
|
774
|
+
return {
|
|
775
|
+
handlers: [handler],
|
|
776
|
+
};
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
export default CacheHandler;
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
```tsx
|
|
783
|
+
// next.config.ts
|
|
784
|
+
const nextConfig = {
|
|
785
|
+
cacheHandler: require.resolve('./cache-handler.mjs'),
|
|
786
|
+
cacheMaxMemorySize: 0, // Disable in-memory cache, use Redis only
|
|
787
|
+
};
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
### S3 Cache Handler
|
|
791
|
+
|
|
792
|
+
For AWS deployments without Redis:
|
|
793
|
+
|
|
794
|
+
```tsx
|
|
795
|
+
// cache-handler.mjs
|
|
796
|
+
import { S3Client, GetObjectCommand, PutObjectCommand } from '@aws-sdk/client-s3';
|
|
797
|
+
|
|
798
|
+
const s3 = new S3Client({ region: process.env.AWS_REGION });
|
|
799
|
+
const BUCKET = process.env.CACHE_BUCKET;
|
|
800
|
+
|
|
801
|
+
export default class CacheHandler {
|
|
802
|
+
async get(key) {
|
|
803
|
+
try {
|
|
804
|
+
const response = await s3.send(new GetObjectCommand({
|
|
805
|
+
Bucket: BUCKET, Key: `cache/${key}`,
|
|
806
|
+
}));
|
|
807
|
+
const body = await response.Body.transformToString();
|
|
808
|
+
return JSON.parse(body);
|
|
809
|
+
} catch (err) {
|
|
810
|
+
if (err.name === 'NoSuchKey') return null;
|
|
811
|
+
throw err;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
async set(key, data, ctx) {
|
|
816
|
+
await s3.send(new PutObjectCommand({
|
|
817
|
+
Bucket: BUCKET,
|
|
818
|
+
Key: `cache/${key}`,
|
|
819
|
+
Body: JSON.stringify({ value: data, lastModified: Date.now() }),
|
|
820
|
+
ContentType: 'application/json',
|
|
821
|
+
}));
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
### Testing Cache Handlers
|
|
827
|
+
|
|
828
|
+
Test your cache handler on every Next.js upgrade. Start multiple instances and verify they share state:
|
|
829
|
+
|
|
830
|
+
```bash
|
|
831
|
+
# Start two instances
|
|
832
|
+
PORT=3001 node .next/standalone/server.js &
|
|
833
|
+
PORT=3002 node .next/standalone/server.js &
|
|
834
|
+
|
|
835
|
+
# Trigger ISR revalidation on instance 1
|
|
836
|
+
curl http://localhost:3001/api/revalidate?path=/meetings
|
|
837
|
+
|
|
838
|
+
# Verify both instances see the update
|
|
839
|
+
curl http://localhost:3001/meetings
|
|
840
|
+
curl http://localhost:3002/meetings
|
|
841
|
+
# Should return identical content
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
### Feature Compatibility (Self-Hosted)
|
|
845
|
+
|
|
846
|
+
| Feature | Single Instance | Multi-Instance | Notes |
|
|
847
|
+
|---------|:-:|:-:|-------|
|
|
848
|
+
| SSR | ✅ | ✅ | No special setup |
|
|
849
|
+
| SSG | ✅ | ✅ | Built at deploy time |
|
|
850
|
+
| ISR | ✅ | Needs cache handler | Filesystem cache breaks across instances |
|
|
851
|
+
| Image Optimisation | ✅ | ✅ | CPU-intensive — consider CDN |
|
|
852
|
+
| Proxy (Middleware) | ✅ | ✅ | Runs on Node.js |
|
|
853
|
+
| `revalidatePath/Tag` | ✅ | Needs cache handler | Must share cache |
|
|
854
|
+
| `next/font` | ✅ | ✅ | Fonts bundled at build time |
|
|
855
|
+
| Draft Mode | ✅ | ✅ | Cookie-based |
|
|
856
|
+
|
|
857
|
+
---
|
|
858
|
+
|
|
859
|
+
## Debug Tools
|
|
860
|
+
|
|
861
|
+
### MCP Debug Endpoint
|
|
862
|
+
|
|
863
|
+
Next.js exposes a debug endpoint at `/_next/mcp` when running in development. This provides JSON-RPC tools for diagnosing issues:
|
|
864
|
+
|
|
865
|
+
| Tool | Purpose |
|
|
866
|
+
|------|---------|
|
|
867
|
+
| `get_errors` | Lists current build and runtime errors |
|
|
868
|
+
| `get_routes` | Shows all registered routes and their types |
|
|
869
|
+
| `get_project_metadata` | Next.js version, config, enabled features |
|
|
870
|
+
| `get_page_metadata` | Metadata for a specific route |
|
|
871
|
+
| `get_logs` | Recent server-side logs |
|
|
872
|
+
| `get_server_action_by_id` | Inspect a specific Server Action |
|
|
873
|
+
|
|
874
|
+
### Partial Rebuilds
|
|
875
|
+
|
|
876
|
+
When debugging a specific route, use `--debug-build-paths` to rebuild only that route:
|
|
877
|
+
|
|
878
|
+
```bash
|
|
879
|
+
pnpm dev --debug-build-paths=/meetings/[id]
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
This speeds up the dev server restart when working on a single page.
|
|
883
|
+
|
|
884
|
+
### Pre-Deployment Checklist
|
|
885
|
+
|
|
886
|
+
1. `pnpm build` completes without errors
|
|
887
|
+
2. `pnpm test` passes all suites
|
|
888
|
+
3. `pnpm lint` reports no issues
|
|
889
|
+
4. All pages tested in both dark and light themes
|
|
890
|
+
5. Images use `next/image` with proper `sizes` and `alt`
|
|
891
|
+
6. Fonts load via `next/font`, no external `<link>` tags
|
|
892
|
+
7. No `console.log` in production code
|
|
893
|
+
8. Health check endpoint responds at `/api/health`
|
|
894
|
+
9. Environment variables documented and configured for target environment
|
|
895
|
+
|
|
896
|
+
---
|
|
897
|
+
|
|
898
|
+
## Core Web Vitals
|
|
899
|
+
|
|
900
|
+
Use `useReportWebVitals` to report performance metrics to your analytics backend:
|
|
901
|
+
|
|
902
|
+
```tsx
|
|
903
|
+
// app/web-vitals.tsx
|
|
904
|
+
'use client';
|
|
905
|
+
|
|
906
|
+
import { useReportWebVitals } from 'next/web-vitals';
|
|
907
|
+
|
|
908
|
+
export function WebVitals() {
|
|
909
|
+
useReportWebVitals(metric => {
|
|
910
|
+
// Send to analytics
|
|
911
|
+
console.log(metric); // Replace with actual analytics call
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
return null;
|
|
915
|
+
}
|
|
916
|
+
```
|
|
917
|
+
|
|
918
|
+
```tsx
|
|
919
|
+
// app/layout.tsx
|
|
920
|
+
import { WebVitals } from './web-vitals';
|
|
921
|
+
|
|
922
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
923
|
+
return (
|
|
924
|
+
<html lang="en">
|
|
925
|
+
<body>
|
|
926
|
+
<WebVitals />
|
|
927
|
+
{children}
|
|
928
|
+
</body>
|
|
929
|
+
</html>
|
|
930
|
+
);
|
|
931
|
+
}
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
Metrics reported: **CLS** (Cumulative Layout Shift), **FCP** (First Contentful Paint), **FID** (First Input Delay), **INP** (Interaction to Next Paint), **LCP** (Largest Contentful Paint), **TTFB** (Time to First Byte).
|
|
935
|
+
|
|
936
|
+
---
|
|
937
|
+
|
|
938
|
+
## Serverless Deployment (OpenNext)
|
|
939
|
+
|
|
940
|
+
[OpenNext](https://open-next.js.org/) adapts Next.js for AWS Lambda, Cloudflare Workers, and other serverless platforms without Vercel:
|
|
941
|
+
|
|
942
|
+
```bash
|
|
943
|
+
# AWS Lambda + CloudFront
|
|
944
|
+
pnpx @opennextjs/aws build
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
Supported targets: AWS Lambda + CloudFront, Cloudflare Workers, Netlify Functions, Deno Deploy.
|