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
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# Routing & Navigation
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [File-Based Routing](#file-based-routing)
|
|
5
|
+
- [Route Segments](#route-segments)
|
|
6
|
+
- [Proxy (Middleware)](#proxy-middleware)
|
|
7
|
+
- [Parallel Routes](#parallel-routes)
|
|
8
|
+
- [Intercepting Routes](#intercepting-routes)
|
|
9
|
+
- [Modal Pattern](#modal-pattern)
|
|
10
|
+
- [Navigation Hooks](#navigation-hooks)
|
|
11
|
+
- [Suspense Boundaries for Hooks](#suspense-boundaries-for-hooks)
|
|
12
|
+
- [Static Route Pre-rendering](#static-route-pre-rendering)
|
|
13
|
+
- [Link Component](#link-component)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## File-Based Routing
|
|
18
|
+
|
|
19
|
+
Next.js App Router uses the filesystem to define routes. Each folder in `app/` is a route segment, and special files within define the UI for that segment.
|
|
20
|
+
|
|
21
|
+
| File | Purpose | Client Component? |
|
|
22
|
+
|------|---------|-------------------|
|
|
23
|
+
| `page.tsx` | Renders the UI for this route | No (RSC default) |
|
|
24
|
+
| `layout.tsx` | Shared wrapper for this segment and children | No |
|
|
25
|
+
| `loading.tsx` | Loading state (auto-wraps page in Suspense) | No |
|
|
26
|
+
| `error.tsx` | Error boundary for this segment | **Yes** |
|
|
27
|
+
| `not-found.tsx` | 404 UI for this segment | No |
|
|
28
|
+
| `route.ts` | API endpoint (no React rendering) | N/A |
|
|
29
|
+
| `template.tsx` | Like layout, but re-renders on every navigation | No |
|
|
30
|
+
| `default.tsx` | Fallback for parallel route slots | No |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Route Segments
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
app/
|
|
38
|
+
├── meetings/ # Static: /meetings
|
|
39
|
+
├── [id]/ # Dynamic: /:id
|
|
40
|
+
├── [...slug]/ # Catch-all: /a/b/c (requires at least one segment)
|
|
41
|
+
├── [[...slug]]/ # Optional catch-all: / or /a/b/c
|
|
42
|
+
├── (dashboard)/ # Route group — ignored in URL
|
|
43
|
+
└── _components/ # Private folder — excluded from routing
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Route Groups
|
|
47
|
+
|
|
48
|
+
Route groups `(name)` organise routes without affecting the URL. Use them to apply different layouts to subsets of routes:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
app/
|
|
52
|
+
├── (auth)/
|
|
53
|
+
│ ├── login/page.tsx # /login — uses auth layout
|
|
54
|
+
│ ├── register/page.tsx # /register — uses auth layout
|
|
55
|
+
│ └── layout.tsx # Minimal layout for auth pages
|
|
56
|
+
├── (app)/
|
|
57
|
+
│ ├── dashboard/page.tsx # /dashboard — uses app layout
|
|
58
|
+
│ └── layout.tsx # Full layout with sidebar
|
|
59
|
+
└── layout.tsx # Root layout
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Private Folders
|
|
63
|
+
|
|
64
|
+
Prefix a folder with `_` to exclude it from routing. Use for co-located components that shouldn't become routes:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
app/meetings/
|
|
68
|
+
├── _components/
|
|
69
|
+
│ └── meeting-filters.tsx # Not a route — co-located helper
|
|
70
|
+
├── page.tsx # /meetings
|
|
71
|
+
└── [id]/
|
|
72
|
+
└── page.tsx # /meetings/:id
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Proxy (Middleware)
|
|
78
|
+
|
|
79
|
+
In Next.js 16, middleware has been renamed to **proxy** for clarity. The file lives at the project root and runs before every request.
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
// proxy.ts (project root)
|
|
83
|
+
import { NextResponse } from 'next/server';
|
|
84
|
+
import type { NextRequest } from 'next/server';
|
|
85
|
+
|
|
86
|
+
export function proxy(request: NextRequest) {
|
|
87
|
+
// Example: redirect unauthenticated users
|
|
88
|
+
const token = request.cookies.get('auth-token');
|
|
89
|
+
|
|
90
|
+
if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
|
|
91
|
+
return NextResponse.redirect(new URL('/login', request.url));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return NextResponse.next();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export const proxyConfig = {
|
|
98
|
+
matcher: ['/dashboard/:path*', '/settings/:path*'],
|
|
99
|
+
};
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
| Version | File | Export | Config |
|
|
103
|
+
|---------|------|--------|--------|
|
|
104
|
+
| v14-15 | `middleware.ts` | `middleware()` | `config` |
|
|
105
|
+
| v16+ | `proxy.ts` | `proxy()` | `proxyConfig` |
|
|
106
|
+
|
|
107
|
+
To migrate: `pnpx @next/codemod@latest upgrade`
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Parallel Routes
|
|
112
|
+
|
|
113
|
+
Parallel routes render multiple pages simultaneously in the same layout. Each slot renders independently and can have its own loading and error states.
|
|
114
|
+
|
|
115
|
+
### File Structure
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
app/
|
|
119
|
+
├── @modal/ # Parallel route slot
|
|
120
|
+
│ ├── default.tsx # Required — returns null
|
|
121
|
+
│ └── (.)meetings/[id]/ # Intercepts /meetings/:id
|
|
122
|
+
│ └── page.tsx # Modal content
|
|
123
|
+
├── meetings/
|
|
124
|
+
│ ├── page.tsx # /meetings (gallery/list)
|
|
125
|
+
│ └── [id]/
|
|
126
|
+
│ └── page.tsx # /meetings/:id (full page)
|
|
127
|
+
├── layout.tsx # Receives children + modal slot
|
|
128
|
+
└── page.tsx
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Layout with Slots
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
// app/layout.tsx
|
|
135
|
+
export default function RootLayout({
|
|
136
|
+
children,
|
|
137
|
+
modal,
|
|
138
|
+
}: {
|
|
139
|
+
children: React.ReactNode;
|
|
140
|
+
modal: React.ReactNode;
|
|
141
|
+
}) {
|
|
142
|
+
return (
|
|
143
|
+
<html lang="en">
|
|
144
|
+
<body>
|
|
145
|
+
{children}
|
|
146
|
+
{modal}
|
|
147
|
+
</body>
|
|
148
|
+
</html>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### default.tsx is Critical
|
|
154
|
+
|
|
155
|
+
Every parallel route slot **must** have a `default.tsx` that returns `null`. Without it, refreshing any page returns a 404 because Next.js cannot determine what to render in the empty slot.
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
// app/@modal/default.tsx
|
|
159
|
+
export default function Default() {
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Intercepting Routes
|
|
167
|
+
|
|
168
|
+
Intercepting routes show a different UI when navigating from within the app versus accessing the URL directly. Combined with parallel routes, they enable modal patterns.
|
|
169
|
+
|
|
170
|
+
### Matchers
|
|
171
|
+
|
|
172
|
+
| Matcher | Intercepts | Example |
|
|
173
|
+
|---------|-----------|---------|
|
|
174
|
+
| `(.)` | Same level | `@modal/(.)meetings` intercepts `/meetings` |
|
|
175
|
+
| `(..)` | One level up | `@modal/(..)settings` intercepts `/settings` from a child |
|
|
176
|
+
| `(..)(..)` | Two levels up | Rarely used |
|
|
177
|
+
| `(...)` | From root | `@modal/(...)meetings` intercepts `/meetings` from anywhere |
|
|
178
|
+
|
|
179
|
+
These match **route segments**, not filesystem paths. A common mistake is thinking `(..)` means "parent folder" — it means "parent route segment."
|
|
180
|
+
|
|
181
|
+
### Hard Navigation Behaviour
|
|
182
|
+
|
|
183
|
+
| Navigation Type | What Renders |
|
|
184
|
+
|----------------|-------------|
|
|
185
|
+
| **Soft navigation** (clicking a Link) | Intercepting route (modal) |
|
|
186
|
+
| **Hard navigation** (URL bar, refresh, bookmark) | Full page (not intercepted) |
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Modal Pattern
|
|
191
|
+
|
|
192
|
+
The complete pattern for an intercepting modal:
|
|
193
|
+
|
|
194
|
+
### Step 1: Link Triggers Interception
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
// app/meetings/page.tsx
|
|
198
|
+
import Link from 'next/link';
|
|
199
|
+
|
|
200
|
+
export default async function MeetingsPage() {
|
|
201
|
+
const meetings = await getMeetings();
|
|
202
|
+
|
|
203
|
+
return (
|
|
204
|
+
<div className="bento-grid">
|
|
205
|
+
{meetings.data.map(meeting => (
|
|
206
|
+
<Link key={meeting.id} href={`/meetings/${meeting.id}`}>
|
|
207
|
+
<MeetingCard meeting={meeting} />
|
|
208
|
+
</Link>
|
|
209
|
+
))}
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Step 2: Intercepting Route Renders Modal
|
|
216
|
+
|
|
217
|
+
```tsx
|
|
218
|
+
// app/@modal/(.)meetings/[id]/page.tsx
|
|
219
|
+
import { getMeeting } from '@/lib/api';
|
|
220
|
+
import { Modal } from '@/components/ui/modal';
|
|
221
|
+
|
|
222
|
+
type Props = { params: Promise<{ id: string }> };
|
|
223
|
+
|
|
224
|
+
export default async function MeetingModal({ params }: Props) {
|
|
225
|
+
const { id } = await params;
|
|
226
|
+
const meeting = await getMeeting(id);
|
|
227
|
+
|
|
228
|
+
return (
|
|
229
|
+
<Modal>
|
|
230
|
+
<h2>{meeting.title}</h2>
|
|
231
|
+
<p>{meeting.status}</p>
|
|
232
|
+
</Modal>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Step 3: Modal Closes with router.back()
|
|
238
|
+
|
|
239
|
+
Use `router.back()` to close modals. Never use `router.push('/')` or `<Link href="/">` — these create broken history entries.
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
// components/ui/modal.tsx
|
|
243
|
+
'use client';
|
|
244
|
+
|
|
245
|
+
import { useRouter } from 'next/navigation';
|
|
246
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
247
|
+
|
|
248
|
+
export function Modal({ children }: { children: React.ReactNode }) {
|
|
249
|
+
const router = useRouter();
|
|
250
|
+
const overlayRef = useRef<HTMLDivElement>(null);
|
|
251
|
+
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
function onKeyDown(e: KeyboardEvent) {
|
|
254
|
+
if (e.key === 'Escape') router.back();
|
|
255
|
+
}
|
|
256
|
+
document.addEventListener('keydown', onKeyDown);
|
|
257
|
+
return () => document.removeEventListener('keydown', onKeyDown);
|
|
258
|
+
}, [router]);
|
|
259
|
+
|
|
260
|
+
const handleOverlayClick = useCallback(
|
|
261
|
+
(e: React.MouseEvent) => {
|
|
262
|
+
if (e.target === overlayRef.current) router.back();
|
|
263
|
+
},
|
|
264
|
+
[router]
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
return (
|
|
268
|
+
<div
|
|
269
|
+
ref={overlayRef}
|
|
270
|
+
onClick={handleOverlayClick}
|
|
271
|
+
className="fixed inset-0 z-50 flex items-center justify-center"
|
|
272
|
+
style={{ backgroundColor: 'oklch(0 0 0 / 0.5)' }}
|
|
273
|
+
>
|
|
274
|
+
<div className="surface-elevated max-w-2xl w-full mx-4 p-6">
|
|
275
|
+
<button
|
|
276
|
+
onClick={() => router.back()}
|
|
277
|
+
className="absolute top-4 right-4"
|
|
278
|
+
aria-label="Close"
|
|
279
|
+
>
|
|
280
|
+
✕
|
|
281
|
+
</button>
|
|
282
|
+
{children}
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Why router.back(), Not router.push()
|
|
290
|
+
|
|
291
|
+
| Method | Behaviour |
|
|
292
|
+
|--------|-----------|
|
|
293
|
+
| `router.back()` | Removes intercepted route from history, returns to previous page, properly unmounts modal |
|
|
294
|
+
| `router.push('/')` | Adds new history entry (back button reopens modal), doesn't clear intercept state, modal may flash or persist |
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Navigation Hooks
|
|
299
|
+
|
|
300
|
+
All navigation hooks require `"use client"`.
|
|
301
|
+
|
|
302
|
+
| Hook | Purpose | Needs Suspense? |
|
|
303
|
+
|------|---------|----------------|
|
|
304
|
+
| `useRouter()` | Programmatic navigation (`push`, `replace`, `back`, `refresh`) | No |
|
|
305
|
+
| `usePathname()` | Current pathname as string | Yes (dynamic routes) |
|
|
306
|
+
| `useSearchParams()` | Read URL search parameters | **Yes (always)** |
|
|
307
|
+
| `useParams()` | Access dynamic route parameters | No |
|
|
308
|
+
| `useSelectedLayoutSegment()` | Active child segment (one level) | No |
|
|
309
|
+
| `useSelectedLayoutSegments()` | All active segments below layout | No |
|
|
310
|
+
| `useLinkStatus()` | Check if a `<Link>` is being prefetched (`'pending'` or `'idle'`) | No |
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Suspense Boundaries for Hooks
|
|
315
|
+
|
|
316
|
+
`useSearchParams()` always requires a Suspense boundary. Without one, the entire page bails out to client-side rendering.
|
|
317
|
+
|
|
318
|
+
```tsx
|
|
319
|
+
// Bad — entire page becomes CSR
|
|
320
|
+
'use client';
|
|
321
|
+
import { useSearchParams } from 'next/navigation';
|
|
322
|
+
|
|
323
|
+
export default function SearchPage() {
|
|
324
|
+
const searchParams = useSearchParams();
|
|
325
|
+
return <div>Query: {searchParams.get('q')}</div>;
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
```tsx
|
|
330
|
+
// Good — wrap in Suspense
|
|
331
|
+
import { Suspense } from 'react';
|
|
332
|
+
import { SearchContent } from '@/components/search-content';
|
|
333
|
+
|
|
334
|
+
export default function SearchPage() {
|
|
335
|
+
return (
|
|
336
|
+
<Suspense fallback={<div>Loading search…</div>}>
|
|
337
|
+
<SearchContent />
|
|
338
|
+
</Suspense>
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
`usePathname()` requires a Suspense boundary in dynamic routes (routes with `[param]` segments). If `generateStaticParams` is used, the boundary is optional.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Static Route Pre-rendering
|
|
348
|
+
|
|
349
|
+
Use `generateStaticParams` to pre-render dynamic routes at build time. This eliminates server-side rendering on each request for known pages.
|
|
350
|
+
|
|
351
|
+
```tsx
|
|
352
|
+
// app/meetings/[id]/page.tsx
|
|
353
|
+
export async function generateStaticParams() {
|
|
354
|
+
const meetings = await getMeetings();
|
|
355
|
+
return meetings.data.map(meeting => ({ id: meeting.id }));
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export default async function MeetingPage({ params }: Props) {
|
|
359
|
+
const { id } = await params;
|
|
360
|
+
const meeting = await getMeeting(id);
|
|
361
|
+
return <MeetingDetail meeting={meeting} />;
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
Pages generated by `generateStaticParams` are statically rendered at build time. Pages with dynamic params not returned by `generateStaticParams` are rendered on-demand and then cached.
|
|
366
|
+
|
|
367
|
+
When `generateStaticParams` is used, `usePathname()` no longer requires a Suspense boundary because the path is known at build time.
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Link Component
|
|
372
|
+
|
|
373
|
+
Always use `next/link` for internal navigation. Never use raw `<a>` tags for internal links.
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
// Bad
|
|
377
|
+
<a href="/meetings">Meetings</a>
|
|
378
|
+
|
|
379
|
+
// Good
|
|
380
|
+
import Link from 'next/link';
|
|
381
|
+
<Link href="/meetings">Meetings</Link>
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Active Link Styling
|
|
385
|
+
|
|
386
|
+
```tsx
|
|
387
|
+
'use client';
|
|
388
|
+
|
|
389
|
+
import Link from 'next/link';
|
|
390
|
+
import { usePathname } from 'next/navigation';
|
|
391
|
+
|
|
392
|
+
export function NavLink({ href, children }: { href: string; children: React.ReactNode }) {
|
|
393
|
+
const pathname = usePathname();
|
|
394
|
+
const isActive = pathname === href;
|
|
395
|
+
|
|
396
|
+
return (
|
|
397
|
+
<Link
|
|
398
|
+
href={href}
|
|
399
|
+
className={isActive ? 'text-primary' : 'text-muted-foreground'}
|
|
400
|
+
>
|
|
401
|
+
{children}
|
|
402
|
+
</Link>
|
|
403
|
+
);
|
|
404
|
+
}
|
|
405
|
+
```
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Security
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
- [The Posture](#the-posture)
|
|
5
|
+
- [XSS: Trust React's Escaping](#xss-trust-reacts-escaping)
|
|
6
|
+
- [The Client Bundle Is Public](#the-client-bundle-is-public)
|
|
7
|
+
- [Server Action Input Validation](#server-action-input-validation)
|
|
8
|
+
- [Auth and Sessions: httpOnly Cookies](#auth-and-sessions-httponly-cookies)
|
|
9
|
+
- [CSRF on Mutations](#csrf-on-mutations)
|
|
10
|
+
- [SSRF on Server Fetches](#ssrf-on-server-fetches)
|
|
11
|
+
- [Content-Security-Policy](#content-security-policy)
|
|
12
|
+
- [Security Review Checklist](#security-review-checklist)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## The Posture
|
|
17
|
+
|
|
18
|
+
A Next.js app runs in two places at once, and the boundary between them is the whole security model. Server Components, Server Actions, and route handlers run on a trusted server; everything else ships to a browser the user controls. Code, props, and environment values that cross into the client are public — assume an attacker reads the bundle and replays every request. This file is the Next.js idiom of the framework security canon (`docs/principles/quality/security.md`); when this file and the canon disagree, the canon wins and this file is the one to fix.
|
|
19
|
+
|
|
20
|
+
The single discipline underneath every rule below: validate and authorize on the server, never trust the client. Client-side validation is UX; the server check is the security boundary (`references/mutations-and-forms.md` → Error Flow).
|
|
21
|
+
|
|
22
|
+
## XSS: Trust React's Escaping
|
|
23
|
+
|
|
24
|
+
React escapes every value interpolated into JSX by default — `{userValue}` cannot break out of its text node. XSS re-enters only when you opt out of that escaping.
|
|
25
|
+
|
|
26
|
+
- `dangerouslySetInnerHTML` is the named opt-out. Render it only with HTML you produced or sanitised server-side (a vetted sanitiser such as DOMPurify); never with a value that originated from a user or an API.
|
|
27
|
+
- A `javascript:` or `data:` URL in an `href`/`src` is script. Validate that user-supplied URLs are `https:` before rendering them.
|
|
28
|
+
- Untrusted JSON parsed and injected as markup is the same hole by another route — keep untrusted data as text.
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
// Hostile — renders attacker markup into a privileged origin
|
|
32
|
+
<div dangerouslySetInnerHTML={{ __html: order.customerNote }} />
|
|
33
|
+
|
|
34
|
+
// Safe — React escapes it; the note is text, not markup
|
|
35
|
+
<div>{order.customerNote}</div>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## The Client Bundle Is Public
|
|
39
|
+
|
|
40
|
+
Every value reachable from client code is shipped to the browser. The `NEXT_PUBLIC_` prefix is the boundary: a variable with that prefix is inlined into the bundle, and a variable without it is unreadable from any `'use client'` module.
|
|
41
|
+
|
|
42
|
+
- Secrets — API keys, signing secrets, database URLs — never carry the `NEXT_PUBLIC_` prefix and are read only in server code (Server Components, Server Actions, route handlers, `lib/api.ts` on the server).
|
|
43
|
+
- A secret consumed by the client is a secret leaked. If a feature "needs" a key in the browser, the call belongs on the server: route it through a Server Action and keep the key server-side.
|
|
44
|
+
- The downward dependency graph (`references/architecture.md`) keeps this honest — schemas and the API client never import client-only code, so server secrets have no path into a client component by construction.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
const apiKey = process.env.UPSTREAM_API_KEY; // server-only — correct
|
|
48
|
+
const pub = process.env.NEXT_PUBLIC_ANALYTICS_ID; // inlined into the bundle — public by design
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Server Action Input Validation
|
|
52
|
+
|
|
53
|
+
A Server Action is a public POST endpoint — anyone can invoke it with any payload, regardless of what the form allows. Every Server Action re-validates its input with the same Zod schema the form uses, on the server, before any work (`references/type-system.md` → Zod as the Contract).
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
'use server';
|
|
57
|
+
|
|
58
|
+
export async function updateOrderAction(
|
|
59
|
+
id: string,
|
|
60
|
+
formData: FormData,
|
|
61
|
+
): Promise<ActionResult<Order>> {
|
|
62
|
+
const principal = await requirePrincipal(); // 1. authenticate the caller
|
|
63
|
+
const parsed = updateOrderSchema.safeParse({ // 2. validate every field
|
|
64
|
+
quantity: Number(formData.get('quantity')),
|
|
65
|
+
note: formData.get('note'),
|
|
66
|
+
});
|
|
67
|
+
if (!parsed.success) {
|
|
68
|
+
return { data: null, error: parsed.error.issues[0].message };
|
|
69
|
+
}
|
|
70
|
+
if (!(await canEditOrder(principal, id))) { // 3. authorize this action on this resource
|
|
71
|
+
return { data: null, error: 'Not found' }; // deny as not-found — do not confirm existence
|
|
72
|
+
}
|
|
73
|
+
// ... mutate, revalidatePath, return ActionResult
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The order is non-negotiable: authenticate, validate, authorize, then act. A Server Action that trusts the form's own validation is unauthenticated and unvalidated.
|
|
78
|
+
|
|
79
|
+
## Auth and Sessions: httpOnly Cookies
|
|
80
|
+
|
|
81
|
+
The session token lives in an `httpOnly`, `Secure`, `SameSite` cookie set by the server — never in `localStorage` or a JS-readable cookie. A token JavaScript can read is a token an XSS payload can exfiltrate; `httpOnly` removes it from script's reach entirely.
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
cookies().set('session', token, {
|
|
85
|
+
httpOnly: true,
|
|
86
|
+
secure: true,
|
|
87
|
+
sameSite: 'lax', // lax/strict is the baseline CSRF defence for cookie auth
|
|
88
|
+
path: '/',
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
- Authentication runs through a proven provider (OIDC); the app does not hand-roll JWT verification or session crypto. Auth is boring technology — `docs/principles/system-design/identity-and-access.md`.
|
|
93
|
+
- The session is read and verified on the server (Server Component / Server Action / route handler), and the proxy (`proxy.ts`) gates protected segments. A client-side `isLoggedIn` flag is UX, never a gate.
|
|
94
|
+
|
|
95
|
+
## CSRF on Mutations
|
|
96
|
+
|
|
97
|
+
Cookie-authenticated mutations need CSRF protection, because the browser attaches the session cookie to cross-site requests automatically. The first layer is `SameSite=lax`/`strict` on the session cookie, which blocks the classic cross-site form post.
|
|
98
|
+
|
|
99
|
+
- Server Actions carry framework-level protection: Next.js verifies an origin/action token, so a third-party page cannot replay one. Keep that — do not expose the same mutation as an unprotected route handler that bypasses it.
|
|
100
|
+
- A route handler that mutates state under cookie auth validates the `Origin` header against an allowlist (and uses a CSRF token if it cannot rely on `SameSite`). A `GET` never mutates.
|
|
101
|
+
|
|
102
|
+
## SSRF on Server Fetches
|
|
103
|
+
|
|
104
|
+
Server-side `fetch` runs from inside your network, so a fetch aimed at an input-supplied URL is an SSRF vector — an attacker points it at cloud metadata endpoints or internal services.
|
|
105
|
+
|
|
106
|
+
- The API client (`lib/api.ts`) targets a configured base URL, never a host taken from the request. Keep outbound targets constant or allowlisted.
|
|
107
|
+
- A feature that must fetch a user-supplied URL (a webhook, an image proxy) validates the resolved host against an allowlist and rejects non-`https:` schemes and private address ranges before the call.
|
|
108
|
+
|
|
109
|
+
## Content-Security-Policy
|
|
110
|
+
|
|
111
|
+
A strict CSP is the second line that contains an XSS that slips past escaping. Set it on responses via the proxy (`proxy.ts`) or `next.config.ts` headers.
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
- `frame-ancestors 'none'` (or an allowlist) blocks clickjacking; pair it with `X-Content-Type-Options: nosniff`.
|
|
118
|
+
- Avoid `'unsafe-inline'` in `script-src`; use a nonce for any inline script Next.js requires. A CSP containing `*` in `script-src` is not a CSP.
|
|
119
|
+
|
|
120
|
+
## Security Review Checklist
|
|
121
|
+
|
|
122
|
+
For any PR touching Server Actions, route handlers, auth, `proxy.ts`, or `dangerouslySetInnerHTML`:
|
|
123
|
+
|
|
124
|
+
- [ ] No `dangerouslySetInnerHTML` on unsanitised or user-origin HTML
|
|
125
|
+
- [ ] No secret without the `NEXT_PUBLIC_` decision being deliberate; no secret read in a `'use client'` module
|
|
126
|
+
- [ ] Every Server Action authenticates, Zod-validates, and authorizes before acting
|
|
127
|
+
- [ ] Session token in an `httpOnly` `Secure` cookie — never `localStorage`
|
|
128
|
+
- [ ] Mutating route handlers check `Origin`; `GET` never mutates
|
|
129
|
+
- [ ] Server fetches target a constant/allowlisted host — no input-supplied URL unchecked
|
|
130
|
+
- [ ] CSP present and not weakened to `*`/`unsafe-inline` script
|
|
131
|
+
- [ ] Authorization decided on the server; no client flag used as a gate
|