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,240 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatFiles,
|
|
3
|
+
generateFiles,
|
|
4
|
+
Tree,
|
|
5
|
+
names,
|
|
6
|
+
} from '@nx/devkit';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { recordGeneratorProvenance } from '../shared/provenance';
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
import {
|
|
11
|
+
promoteEngineerSkill,
|
|
12
|
+
deployStackDocs,
|
|
13
|
+
ensureOptionalInfra,
|
|
14
|
+
readProjectPrefix,
|
|
15
|
+
} from '../shared/scaffold-helpers';
|
|
16
|
+
|
|
17
|
+
export interface GoMicroserviceGeneratorSchema {
|
|
18
|
+
name: string;
|
|
19
|
+
messaging: 'none' | 'kafka' | 'gcp-pubsub';
|
|
20
|
+
auth: 'none' | 'service' | 'clerk';
|
|
21
|
+
websockets: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default async function (tree: Tree, options: GoMicroserviceGeneratorSchema) {
|
|
25
|
+
// Derive naming variants
|
|
26
|
+
const serviceNames = names(options.name);
|
|
27
|
+
// Using the workspace root, or you might want to place it in `services/`
|
|
28
|
+
// We'll scaffold it in `services/${serviceNames.fileName}` by default.
|
|
29
|
+
const projectRoot = `services/${serviceNames.fileName}`;
|
|
30
|
+
|
|
31
|
+
// Calculate assignedPort based on docker-compose.yml (if it exists)
|
|
32
|
+
let assignedPort = 4000;
|
|
33
|
+
let composeDoc: any = null;
|
|
34
|
+
if (tree.exists('docker-compose.yml')) {
|
|
35
|
+
try {
|
|
36
|
+
const yaml = require('yaml');
|
|
37
|
+
const composeContent = tree.read('docker-compose.yml', 'utf-8');
|
|
38
|
+
composeDoc = yaml.parseDocument(composeContent);
|
|
39
|
+
|
|
40
|
+
const usedPorts = new Set<number>();
|
|
41
|
+
|
|
42
|
+
// Collect ports from docker-compose.yml
|
|
43
|
+
const servicesMap = composeDoc.get('services');
|
|
44
|
+
if (servicesMap && servicesMap.items) {
|
|
45
|
+
for (const item of servicesMap.items) {
|
|
46
|
+
const service = item.value;
|
|
47
|
+
if (service && service.get) {
|
|
48
|
+
const ports = service.get('ports');
|
|
49
|
+
if (ports && ports.items) {
|
|
50
|
+
for (const pItem of ports.items) {
|
|
51
|
+
const portStr = String(pItem.value || pItem);
|
|
52
|
+
const match = portStr.match(/^(\d+):/);
|
|
53
|
+
if (match) {
|
|
54
|
+
usedPorts.add(parseInt(match[1], 10));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Also collect ports from .env files of natively-run services (not in docker-compose)
|
|
63
|
+
if (tree.exists('services')) {
|
|
64
|
+
for (const svcName of tree.children('services') ?? []) {
|
|
65
|
+
const envPath = `services/${svcName}/.env`;
|
|
66
|
+
if (tree.exists(envPath)) {
|
|
67
|
+
const envContent = tree.read(envPath, 'utf-8') ?? '';
|
|
68
|
+
for (const line of envContent.split('\n')) {
|
|
69
|
+
const m = line.match(/^(?:PORT|SERVER_PORT)=(\d+)/);
|
|
70
|
+
if (m) usedPorts.add(parseInt(m[1], 10));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
while (usedPorts.has(assignedPort)) {
|
|
77
|
+
assignedPort++;
|
|
78
|
+
}
|
|
79
|
+
} catch (e) {
|
|
80
|
+
console.warn('Failed to parse docker-compose.yml for port calculation:', e);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Read EJS templates
|
|
85
|
+
const templateOptions = {
|
|
86
|
+
...options,
|
|
87
|
+
...serviceNames,
|
|
88
|
+
assignedPort,
|
|
89
|
+
tmpl: '' // required by generateFiles
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
generateFiles(
|
|
93
|
+
tree,
|
|
94
|
+
path.join(__dirname, '..', '..', '..', '..', 'src', 'generators', 'go-microservice', 'files'),
|
|
95
|
+
projectRoot,
|
|
96
|
+
templateOptions
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
deployStackDocs(tree, path.join(__dirname, '..', '..', '..', '..', 'src', 'generators', 'go-microservice', 'docs'));
|
|
100
|
+
|
|
101
|
+
// Auto-inject into docker-compose.yml if it exists
|
|
102
|
+
if (composeDoc) {
|
|
103
|
+
try {
|
|
104
|
+
const yaml = require('yaml');
|
|
105
|
+
if (!composeDoc.get('services')) {
|
|
106
|
+
// createNode so the result is a YAMLMap with .has/.set — a plain {} is
|
|
107
|
+
// not, and the base compose no longer ships a services: block.
|
|
108
|
+
composeDoc.set('services', composeDoc.createNode({}));
|
|
109
|
+
}
|
|
110
|
+
const servicesMap = composeDoc.get('services');
|
|
111
|
+
|
|
112
|
+
if (!servicesMap.has(serviceNames.fileName)) {
|
|
113
|
+
// Only wire the infrastructure this service actually uses. Redis backs
|
|
114
|
+
// the WebSocket hub; the Pub/Sub emulator backs GCP Pub/Sub messaging.
|
|
115
|
+
// A service using neither should declare neither.
|
|
116
|
+
const usesRedis = options.websockets;
|
|
117
|
+
const usesPubSub = options.messaging === 'gcp-pubsub';
|
|
118
|
+
|
|
119
|
+
const environment: string[] = [
|
|
120
|
+
`SERVER_PORT=${assignedPort}`,
|
|
121
|
+
`DATABASE_URL=postgres://\${DB_USER:-postgres}:\${DB_PASSWORD:-postgres}@db:5432/\${DB_NAME:-${serviceNames.fileName}}?sslmode=disable`,
|
|
122
|
+
'DB_HOST=db',
|
|
123
|
+
'DB_PORT=5432',
|
|
124
|
+
'DB_USER=${DB_USER:-postgres}',
|
|
125
|
+
'DB_PASSWORD=${DB_PASSWORD:-postgres}',
|
|
126
|
+
`DB_NAME=\${DB_NAME:-${serviceNames.fileName}}`
|
|
127
|
+
];
|
|
128
|
+
if (usesRedis) {
|
|
129
|
+
environment.push('REDIS_URL=redis:6379');
|
|
130
|
+
}
|
|
131
|
+
if (usesPubSub) {
|
|
132
|
+
environment.push('PUBSUB_EMULATOR_HOST=pubsub:${PUBSUB_PORT:-8085}');
|
|
133
|
+
}
|
|
134
|
+
environment.push(
|
|
135
|
+
'OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4317',
|
|
136
|
+
'OTEL_EXPORTER_OTLP_PROTOCOL=grpc'
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const dependsOn: Record<string, { condition: string }> = {
|
|
140
|
+
db: { condition: 'service_healthy' }
|
|
141
|
+
};
|
|
142
|
+
if (usesRedis) {
|
|
143
|
+
dependsOn.redis = { condition: 'service_healthy' };
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const newService: Record<string, unknown> = {
|
|
147
|
+
build: {
|
|
148
|
+
context: `./${projectRoot}`,
|
|
149
|
+
dockerfile: 'Dockerfile.dev'
|
|
150
|
+
},
|
|
151
|
+
container_name: serviceNames.fileName,
|
|
152
|
+
restart: 'unless-stopped',
|
|
153
|
+
ports: [
|
|
154
|
+
`${assignedPort}:${assignedPort}`
|
|
155
|
+
],
|
|
156
|
+
environment,
|
|
157
|
+
// The golang:alpine runtime image has no curl, but ships busybox
|
|
158
|
+
// wget, which probes the health endpoint without an extra binary.
|
|
159
|
+
healthcheck: {
|
|
160
|
+
test: [
|
|
161
|
+
'CMD',
|
|
162
|
+
'wget',
|
|
163
|
+
'-q',
|
|
164
|
+
'--spider',
|
|
165
|
+
`http://localhost:${assignedPort}/health`
|
|
166
|
+
],
|
|
167
|
+
interval: '10s',
|
|
168
|
+
timeout: '5s',
|
|
169
|
+
retries: 5,
|
|
170
|
+
start_period: '20s'
|
|
171
|
+
},
|
|
172
|
+
depends_on: dependsOn,
|
|
173
|
+
networks: [
|
|
174
|
+
'groundwork-net'
|
|
175
|
+
]
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
servicesMap.set(serviceNames.fileName, newService);
|
|
179
|
+
// A Go microservice always uses a per-service database and exports
|
|
180
|
+
// telemetry, so it provisions db + jaeger on demand (they are no longer
|
|
181
|
+
// in the base compose).
|
|
182
|
+
ensureOptionalInfra(composeDoc, servicesMap, {
|
|
183
|
+
usesRedis,
|
|
184
|
+
usesPubSub,
|
|
185
|
+
usesDb: true,
|
|
186
|
+
usesTelemetry: true,
|
|
187
|
+
projectPrefix: readProjectPrefix(tree),
|
|
188
|
+
});
|
|
189
|
+
tree.write('docker-compose.yml', composeDoc.toString());
|
|
190
|
+
}
|
|
191
|
+
} catch (e) {
|
|
192
|
+
console.warn('Failed to update docker-compose.yml:', e);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (!options.websockets) {
|
|
197
|
+
tree.delete(`${projectRoot}/internal/websocket`);
|
|
198
|
+
tree.delete(`${projectRoot}/internal/entrypoints/api/websocket_handler.go`);
|
|
199
|
+
tree.delete(`${projectRoot}/asyncapi-ws.yaml`);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (options.messaging === 'none') {
|
|
203
|
+
tree.delete(`${projectRoot}/asyncapi-pubsub.yaml`);
|
|
204
|
+
tree.delete(`${projectRoot}/internal/core/service/message_queue.go`);
|
|
205
|
+
tree.delete(`${projectRoot}/internal/core/service/outbox_repository.go`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (options.messaging !== 'kafka') {
|
|
209
|
+
tree.delete(`${projectRoot}/internal/kafka/kafka.go`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (options.messaging !== 'gcp-pubsub') {
|
|
213
|
+
tree.delete(`${projectRoot}/internal/pubsub/gcp_pubsub.go`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (options.auth !== 'clerk') {
|
|
217
|
+
tree.delete(`${projectRoot}/internal/entrypoints/api/middleware_auth.go`);
|
|
218
|
+
tree.delete(`${projectRoot}/internal/entrypoints/api/auth_middleware_test.go`);
|
|
219
|
+
tree.delete(`${projectRoot}/internal/entrypoints/api/clerk_webhook.go`);
|
|
220
|
+
tree.delete(`${projectRoot}/internal/entrypoints/api/clerk_webhook_test.go`);
|
|
221
|
+
tree.delete(`${projectRoot}/internal/core/domain/user.go`);
|
|
222
|
+
tree.delete(`${projectRoot}/internal/core/service/user_repository.go`);
|
|
223
|
+
tree.delete(`${projectRoot}/internal/core/service/user_service.go`);
|
|
224
|
+
tree.delete(`${projectRoot}/internal/postgres/user_repository.go`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
promoteEngineerSkill(tree, 'groundwork-go-engineer');
|
|
228
|
+
|
|
229
|
+
await formatFiles(tree);
|
|
230
|
+
|
|
231
|
+
recordGeneratorProvenance(tree, 'go-microservice', options as unknown as Record<string, unknown>);
|
|
232
|
+
|
|
233
|
+
return () => {
|
|
234
|
+
try {
|
|
235
|
+
execSync('go mod tidy', { cwd: projectRoot, stdio: 'inherit' });
|
|
236
|
+
} catch (e) {
|
|
237
|
+
console.warn(`Failed to run go mod tidy in ${projectRoot}:`, e);
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"id": "go-microservice",
|
|
4
|
+
"title": "Go Microservice",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"properties": {
|
|
7
|
+
"name": {
|
|
8
|
+
"type": "string",
|
|
9
|
+
"description": "The name of the microservice",
|
|
10
|
+
"$default": {
|
|
11
|
+
"$source": "argv",
|
|
12
|
+
"index": 0
|
|
13
|
+
},
|
|
14
|
+
"x-prompt": "What name would you like to use for the service?"
|
|
15
|
+
},
|
|
16
|
+
"messaging": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"enum": ["none", "kafka", "gcp-pubsub"],
|
|
19
|
+
"default": "none",
|
|
20
|
+
"description": "Include the Transactional Outbox pattern and message broker configuration",
|
|
21
|
+
"x-prompt": {
|
|
22
|
+
"message": "Which message broker do you want to use for the outbox pattern?",
|
|
23
|
+
"type": "list",
|
|
24
|
+
"items": [
|
|
25
|
+
{ "value": "none", "label": "None" },
|
|
26
|
+
{ "value": "kafka", "label": "Kafka" },
|
|
27
|
+
{ "value": "gcp-pubsub", "label": "Google Cloud Pub/Sub" }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"auth": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"enum": ["none", "service", "clerk"],
|
|
34
|
+
"default": "none",
|
|
35
|
+
"description": "The level of authentication boilerplate to include",
|
|
36
|
+
"x-prompt": {
|
|
37
|
+
"message": "Which authentication boilerplate should we include?",
|
|
38
|
+
"type": "list",
|
|
39
|
+
"items": [
|
|
40
|
+
{
|
|
41
|
+
"value": "none",
|
|
42
|
+
"label": "None"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"value": "service",
|
|
46
|
+
"label": "Service-to-Service Auth Only"
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"value": "clerk",
|
|
50
|
+
"label": "Full Clerk User & Service Auth"
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"websockets": {
|
|
56
|
+
"type": "boolean",
|
|
57
|
+
"description": "Include WebSocket Hub, Session Manager, and AsyncAPI v3 generation",
|
|
58
|
+
"default": false,
|
|
59
|
+
"x-prompt": "Do you want to enable WebSockets?"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"required": ["name"]
|
|
63
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Frontend
|
|
3
|
+
description: React 19, Server Components, SWR, Tailwind, and the design language of a Next.js application.
|
|
4
|
+
status: active
|
|
5
|
+
last_reviewed: 2026-05-26
|
|
6
|
+
---
|
|
7
|
+
# Frontend
|
|
8
|
+
|
|
9
|
+
## TL;DR
|
|
10
|
+
|
|
11
|
+
The frontend is Next.js 16 with React 19 Server Components, SWR for client-side data, and Tailwind for styling. We render on the server by default, hydrate the minimum needed for interactivity, and keep data-fetching at the leaves. The design language is consistent, calm, and accessible first.
|
|
12
|
+
|
|
13
|
+
## Why this matters
|
|
14
|
+
|
|
15
|
+
Frontend engineering in 2026 is no longer a "client-side" discipline. Most pixels are rendered on the server before they reach the browser, and the browser's job is to stay responsive to the user's input rather than to fetch data on their behalf. Getting this split right — what runs on the server, what runs on the client, what streams in between — is the single biggest determinant of how fast and how reliable the app feels. It is also where most frontend bugs live.
|
|
16
|
+
|
|
17
|
+
## Our principles
|
|
18
|
+
|
|
19
|
+
### 1. Server components are the default
|
|
20
|
+
|
|
21
|
+
Every component starts as a Server Component. We add `"use client"` only when we need state, events, or browser-only APIs. The economic argument is simple: every client component costs download, parse, hydrate, and memory on every user's device. Server components cost none of that. The ratio of server-to-client components is tracked and kept high.
|
|
22
|
+
|
|
23
|
+
### 2. Data fetches at the leaves, not the root
|
|
24
|
+
|
|
25
|
+
Data fetching happens in the component that actually renders the data, not in a page-level fetcher that passes everything down through props. This lets Suspense boundaries stream exactly as deep as they need to, and it keeps prop-drilling in check. The exception is when two leaves need the same data — then we fetch once in a common ancestor and share via React's built-in request deduplication.
|
|
26
|
+
|
|
27
|
+
### 3. SWR for client-interactive state
|
|
28
|
+
|
|
29
|
+
For state that must respond to user interaction in real time — live views, session state, optimistic updates — we use SWR. One cache, one invalidation story, one mental model. We do not mix query libraries in the same app.
|
|
30
|
+
|
|
31
|
+
### 4. Styling is Tailwind utilities, composed
|
|
32
|
+
|
|
33
|
+
We style with Tailwind utility classes. When a composition of utilities gets long or is repeated, we extract a component — not a custom CSS class. Component extraction keeps the `className` strings honest; new CSS classes are where design systems go to die of untracked one-offs.
|
|
34
|
+
|
|
35
|
+
### 5. The design system is a library, not a guideline
|
|
36
|
+
|
|
37
|
+
Buttons, inputs, modals, tooltips — every primitive is a typed, reviewed component in the shared component library. Ad-hoc styling of a button in a feature folder is a smell; the fix is to add the variant to the library, not to reimplement it.
|
|
38
|
+
|
|
39
|
+
### 6. Accessibility is a baseline, not a feature
|
|
40
|
+
|
|
41
|
+
Every interactive component supports keyboard navigation, is screen-reader labelled, and meets WCAG 2.2 AA contrast at minimum. Accessibility failures block merges the same way type errors do. The golden path for every new UI begins with "can I get to it, use it, and understand it with just the keyboard and a screen reader?"
|
|
42
|
+
|
|
43
|
+
### 7. Client state is recoverable
|
|
44
|
+
|
|
45
|
+
We do not store state in React that cannot be rebuilt from the server or the URL. Refreshing the page is the end-to-end test of this: if the user loses context after a refresh, we are holding state we should not. The URL is a first-class state container; so are Server Components.
|
|
46
|
+
|
|
47
|
+
### 8. Performance budgets are enforced in CI
|
|
48
|
+
|
|
49
|
+
Largest Contentful Paint, Interaction-to-Next-Paint, JS bundle size — all tracked in CI with budgets. A PR that regresses a budget requires an explicit waiver. Performance is never negotiated after the fact; it is designed in.
|
|
50
|
+
|
|
51
|
+
## Anti-patterns we reject
|
|
52
|
+
|
|
53
|
+
- **`useEffect` for data fetching.** `useEffect` is an escape hatch for non-React systems; it is not a data-fetching primitive. Use Server Components or SWR.
|
|
54
|
+
- **Context for everything.** React Context is a tool for genuinely app-wide concerns (theme, auth, locale). Using it to avoid prop-drilling on three levels is overreach.
|
|
55
|
+
- **CSS Modules alongside Tailwind.** One styling system. Not three.
|
|
56
|
+
- **Ad-hoc design primitives.** Every new button variant is a tax on the design system. If it needs a variant, add it to the library.
|
|
57
|
+
- **State that cannot survive refresh.** Modals that disappear on refresh lose user context; counters that reset on refresh are not counters.
|
|
58
|
+
- **"Fix it in a later PR" accessibility.** The later PR will not happen. Ship accessible or ship later.
|
|
59
|
+
|
|
60
|
+
## Further reading
|
|
61
|
+
|
|
62
|
+
- *React documentation* ([react.dev](https://react.dev)) — the canonical source for the Server Component mental model.
|
|
63
|
+
- *Patterns.dev*, Lydia Hallie & Addy Osmani — a clean survey of modern frontend patterns.
|
|
64
|
+
- *Inclusive Components*, Heydon Pickering — the pattern language of accessible component design.
|
|
65
|
+
- *Refactoring UI*, Schoger & Wathan — the design vocabulary that informs how we compose Tailwind.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Environment Configuration
|
|
2
|
+
# Copy this file to .env.local and fill in the values
|
|
3
|
+
<% if (apiProxy) { %>
|
|
4
|
+
# Server-side only: URL of the backend API (no trailing slash).
|
|
5
|
+
# Drives the HTTP proxy (/api/proxy) and runtime config (/api/config).
|
|
6
|
+
API_URL=http://localhost:4000
|
|
7
|
+
<% } %>
|
|
8
|
+
<% if (auth === 'clerk') { %>
|
|
9
|
+
# Clerk Auth (REQUIRED — get from https://dashboard.clerk.com → API Keys)
|
|
10
|
+
# Use pk_test_ / sk_test_ keys for local dev
|
|
11
|
+
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
|
|
12
|
+
CLERK_SECRET_KEY=sk_test_...
|
|
13
|
+
|
|
14
|
+
# Clerk Routing
|
|
15
|
+
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
|
|
16
|
+
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
|
|
17
|
+
NEXT_PUBLIC_CLERK_SIGN_IN_FALLBACK_REDIRECT_URL=/
|
|
18
|
+
NEXT_PUBLIC_CLERK_SIGN_UP_FALLBACK_REDIRECT_URL=/
|
|
19
|
+
<% } %>
|
|
20
|
+
# OpenTelemetry
|
|
21
|
+
OTEL_SERVICE_NAME=<%= fileName %>
|
|
22
|
+
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
23
|
+
# Browser-reachable OTLP HTTP endpoint for client-side spans (NOT the in-container host).
|
|
24
|
+
NEXT_PUBLIC_OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# ── Base ─────────────────────────────────────────────────────────────────────
|
|
2
|
+
FROM node:22-alpine AS base
|
|
3
|
+
ENV PNPM_HOME="/pnpm"
|
|
4
|
+
ENV PATH="$PNPM_HOME:$PATH"
|
|
5
|
+
RUN corepack enable
|
|
6
|
+
|
|
7
|
+
# ── Dependencies ─────────────────────────────────────────────────────────────
|
|
8
|
+
FROM base AS deps
|
|
9
|
+
RUN apk add --no-cache libc6-compat
|
|
10
|
+
WORKDIR /app
|
|
11
|
+
|
|
12
|
+
COPY package.json pnpm-lock.yaml ./
|
|
13
|
+
# --trust-lockfile skips re-running pnpm's supply-chain release-age verification
|
|
14
|
+
# against each entry: the lockfile was just produced by this project's own
|
|
15
|
+
# `pnpm install` and is the trusted build input, so the check only blocks the
|
|
16
|
+
# image on transiently too-new deps (ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION).
|
|
17
|
+
RUN pnpm install --frozen-lockfile --ignore-scripts --trust-lockfile
|
|
18
|
+
|
|
19
|
+
# ── Build ────────────────────────────────────────────────────────────────────
|
|
20
|
+
FROM base AS builder
|
|
21
|
+
WORKDIR /app
|
|
22
|
+
<% if (auth === 'clerk') { %>
|
|
23
|
+
ARG NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
|
|
24
|
+
ENV NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=$NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
|
|
25
|
+
<% } %>
|
|
26
|
+
COPY --from=deps /app/node_modules ./node_modules
|
|
27
|
+
COPY . .
|
|
28
|
+
|
|
29
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
30
|
+
RUN pnpm run build
|
|
31
|
+
|
|
32
|
+
# ── Runtime ──────────────────────────────────────────────────────────────────
|
|
33
|
+
FROM base AS runner
|
|
34
|
+
WORKDIR /app
|
|
35
|
+
|
|
36
|
+
ENV NODE_ENV=production
|
|
37
|
+
ENV NEXT_TELEMETRY_DISABLED=1
|
|
38
|
+
|
|
39
|
+
RUN addgroup --system --gid 1001 nodejs
|
|
40
|
+
RUN adduser --system --uid 1001 nextjs
|
|
41
|
+
|
|
42
|
+
# Copy standalone output (requires output: 'standalone' in next.config.mjs)
|
|
43
|
+
COPY --from=builder /app/public ./public
|
|
44
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
|
45
|
+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
|
46
|
+
|
|
47
|
+
USER nextjs
|
|
48
|
+
|
|
49
|
+
EXPOSE <%= assignedPort %>
|
|
50
|
+
ENV PORT=<%= assignedPort %>
|
|
51
|
+
ENV HOSTNAME="0.0.0.0"
|
|
52
|
+
|
|
53
|
+
CMD ["node", "server.js"]
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Exposes runtime configuration to the client.
|
|
5
|
+
*
|
|
6
|
+
* This is how the browser discovers the WebSocket URL without any
|
|
7
|
+
* NEXT_PUBLIC_ build-time variables. The single API_URL env var
|
|
8
|
+
* drives both the HTTP proxy and this config endpoint.
|
|
9
|
+
*
|
|
10
|
+
* API_URL is validated before transforming http(s) → ws(s). A malformed
|
|
11
|
+
* value fails loud with a 500 rather than emitting a broken WebSocket URL.
|
|
12
|
+
*/
|
|
13
|
+
export function GET() {
|
|
14
|
+
const apiUrl = process.env.API_URL ?? "http://localhost:4000";
|
|
15
|
+
|
|
16
|
+
let parsed: URL;
|
|
17
|
+
try {
|
|
18
|
+
parsed = new URL(apiUrl);
|
|
19
|
+
} catch {
|
|
20
|
+
return NextResponse.json(
|
|
21
|
+
{ detail: "API_URL is not a valid URL" },
|
|
22
|
+
{ status: 500 }
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
27
|
+
return NextResponse.json(
|
|
28
|
+
{ detail: "API_URL must use http or https" },
|
|
29
|
+
{ status: 500 }
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// http → ws, https → wss (anchored to the protocol, not a blind replace).
|
|
34
|
+
const wsProtocol = parsed.protocol === "https:" ? "wss:" : "ws:";
|
|
35
|
+
parsed.protocol = wsProtocol;
|
|
36
|
+
const wsUrl = `${parsed.origin}/ws`;
|
|
37
|
+
|
|
38
|
+
return NextResponse.json({ wsUrl });
|
|
39
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @vitest-environment node
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
import { GET } from "./route";
|
|
4
|
+
|
|
5
|
+
describe("GET /api/healthz", () => {
|
|
6
|
+
it("returns 200 with a healthy status and timestamp", async () => {
|
|
7
|
+
const res = await GET();
|
|
8
|
+
expect(res.status).toBe(200);
|
|
9
|
+
const body = await res.json();
|
|
10
|
+
expect(body.status).toBe("healthy");
|
|
11
|
+
expect(typeof body.timestamp).toBe("string");
|
|
12
|
+
// timestamp must be a valid ISO date.
|
|
13
|
+
expect(Number.isNaN(Date.parse(body.timestamp))).toBe(false);
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// @vitest-environment node
|
|
2
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
3
|
+
import { NextRequest } from "next/server";
|
|
4
|
+
import { GET } from "./route";
|
|
5
|
+
|
|
6
|
+
function makeRequest(path: string): NextRequest {
|
|
7
|
+
return new NextRequest(new Request(`http://localhost/api/proxy/${path}`));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function makeParams(path: string[]) {
|
|
11
|
+
return { params: Promise.resolve({ path }) };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe("api proxy error handling", () => {
|
|
15
|
+
const realFetch = global.fetch;
|
|
16
|
+
|
|
17
|
+
beforeEach(() => {
|
|
18
|
+
process.env.API_URL = "http://upstream.test";
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
global.fetch = realFetch;
|
|
23
|
+
vi.restoreAllMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("forwards an upstream 502 as a 502", async () => {
|
|
27
|
+
global.fetch = vi.fn(async () =>
|
|
28
|
+
new Response("bad gateway", { status: 502, statusText: "Bad Gateway" })
|
|
29
|
+
) as unknown as typeof fetch;
|
|
30
|
+
|
|
31
|
+
const res = await GET(makeRequest("entities"), makeParams(["entities"]));
|
|
32
|
+
expect(res.status).toBe(502);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it("maps an upstream fetch failure (e.g. timeout/abort) to a 502", async () => {
|
|
36
|
+
global.fetch = vi.fn(async () => {
|
|
37
|
+
// Simulate an AbortController timeout / network failure: fetch rejects.
|
|
38
|
+
throw new DOMException("The operation was aborted.", "AbortError");
|
|
39
|
+
}) as unknown as typeof fetch;
|
|
40
|
+
|
|
41
|
+
const res = await GET(makeRequest("entities"), makeParams(["entities"]));
|
|
42
|
+
expect(res.status).toBe(502);
|
|
43
|
+
const body = await res.json();
|
|
44
|
+
expect(body.detail).toBe("Backend service unavailable");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("passes through a successful upstream status", async () => {
|
|
48
|
+
global.fetch = vi.fn(async () =>
|
|
49
|
+
new Response(JSON.stringify({ ok: true }), { status: 200 })
|
|
50
|
+
) as unknown as typeof fetch;
|
|
51
|
+
|
|
52
|
+
const res = await GET(makeRequest("entities"), makeParams(["entities"]));
|
|
53
|
+
expect(res.status).toBe(200);
|
|
54
|
+
});
|
|
55
|
+
});
|