@geraldmaron/construct 1.0.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/.env.example +69 -0
- package/LICENSE +21 -0
- package/README.md +344 -0
- package/agents/prompts/cx-accessibility.md +29 -0
- package/agents/prompts/cx-ai-engineer.md +31 -0
- package/agents/prompts/cx-architect.md +40 -0
- package/agents/prompts/cx-business-strategist.md +25 -0
- package/agents/prompts/cx-data-analyst.md +30 -0
- package/agents/prompts/cx-data-engineer.md +32 -0
- package/agents/prompts/cx-debugger.md +27 -0
- package/agents/prompts/cx-designer.md +33 -0
- package/agents/prompts/cx-devil-advocate.md +36 -0
- package/agents/prompts/cx-docs-keeper.md +50 -0
- package/agents/prompts/cx-engineer.md +36 -0
- package/agents/prompts/cx-evaluator.md +26 -0
- package/agents/prompts/cx-explorer.md +38 -0
- package/agents/prompts/cx-legal-compliance.md +25 -0
- package/agents/prompts/cx-operations.md +28 -0
- package/agents/prompts/cx-orchestrator.md +30 -0
- package/agents/prompts/cx-platform-engineer.md +25 -0
- package/agents/prompts/cx-product-manager.md +30 -0
- package/agents/prompts/cx-qa.md +42 -0
- package/agents/prompts/cx-rd-lead.md +25 -0
- package/agents/prompts/cx-release-manager.md +31 -0
- package/agents/prompts/cx-researcher.md +31 -0
- package/agents/prompts/cx-reviewer.md +36 -0
- package/agents/prompts/cx-security.md +37 -0
- package/agents/prompts/cx-sre.md +26 -0
- package/agents/prompts/cx-test-automation.md +35 -0
- package/agents/prompts/cx-trace-reviewer.md +76 -0
- package/agents/prompts/cx-ux-researcher.md +30 -0
- package/agents/registry.json +879 -0
- package/agents/teams.json +94 -0
- package/bin/construct +613 -0
- package/commands/build/feature.md +21 -0
- package/commands/build/fix.md +20 -0
- package/commands/design/access.md +19 -0
- package/commands/design/flow.md +16 -0
- package/commands/design/ui.md +18 -0
- package/commands/measure/experiment.md +18 -0
- package/commands/measure/metrics.md +18 -0
- package/commands/measure/results.md +18 -0
- package/commands/plan/api.md +19 -0
- package/commands/plan/challenge.md +18 -0
- package/commands/plan/decide.md +20 -0
- package/commands/plan/feature.md +49 -0
- package/commands/plan/requirements.md +24 -0
- package/commands/remember/context.md +26 -0
- package/commands/remember/handoff.md +19 -0
- package/commands/remember/runbook.md +20 -0
- package/commands/review/code.md +21 -0
- package/commands/review/quality.md +19 -0
- package/commands/review/security.md +16 -0
- package/commands/ship/ready.md +19 -0
- package/commands/ship/release.md +19 -0
- package/commands/ship/status.md +18 -0
- package/commands/understand/docs.md +22 -0
- package/commands/understand/research.md +22 -0
- package/commands/understand/this.md +23 -0
- package/commands/understand/why.md +18 -0
- package/commands/work/clean.md +32 -0
- package/commands/work/drive.md +69 -0
- package/commands/work/optimize-prompts.md +46 -0
- package/commands/work/parallel-review.md +40 -0
- package/db/migrations/001_init.sql +38 -0
- package/langfuse/docker-compose.yml +82 -0
- package/lib/audit-skills.mjs +118 -0
- package/lib/auto-docs.mjs +293 -0
- package/lib/cli-commands.mjs +409 -0
- package/lib/codex-config.mjs +114 -0
- package/lib/comment-lint.mjs +191 -0
- package/lib/completions.mjs +170 -0
- package/lib/context-state.mjs +99 -0
- package/lib/cost.mjs +213 -0
- package/lib/distill.mjs +403 -0
- package/lib/efficiency.mjs +139 -0
- package/lib/env-config.mjs +53 -0
- package/lib/eval-harness.mjs +59 -0
- package/lib/features.mjs +209 -0
- package/lib/headhunt.mjs +597 -0
- package/lib/hooks/adaptive-lint.mjs +112 -0
- package/lib/hooks/agent-tracker.mjs +50 -0
- package/lib/hooks/bootstrap-guard.mjs +90 -0
- package/lib/hooks/comment-lint.mjs +26 -0
- package/lib/hooks/config-protection.mjs +52 -0
- package/lib/hooks/console-warn.mjs +43 -0
- package/lib/hooks/context-window-recovery.mjs +90 -0
- package/lib/hooks/continuation-enforcer.mjs +72 -0
- package/lib/hooks/dep-audit.mjs +155 -0
- package/lib/hooks/drive-guard.mjs +89 -0
- package/lib/hooks/edit-accumulator.mjs +36 -0
- package/lib/hooks/edit-error-recovery.mjs +46 -0
- package/lib/hooks/edit-guard.mjs +109 -0
- package/lib/hooks/env-check.mjs +80 -0
- package/lib/hooks/guard-bash.mjs +83 -0
- package/lib/hooks/mcp-audit.mjs +57 -0
- package/lib/hooks/mcp-health-check.mjs +51 -0
- package/lib/hooks/mcp-task-scope.mjs +47 -0
- package/lib/hooks/model-fallback.mjs +105 -0
- package/lib/hooks/pre-compact.mjs +212 -0
- package/lib/hooks/pre-push-gate.mjs +129 -0
- package/lib/hooks/read-tracker.mjs +129 -0
- package/lib/hooks/registry-sync.mjs +23 -0
- package/lib/hooks/scan-secrets.mjs +76 -0
- package/lib/hooks/session-start.mjs +95 -0
- package/lib/hooks/stop-notify.mjs +191 -0
- package/lib/hooks/stop-typecheck.mjs +83 -0
- package/lib/hooks/task-completed-guard.mjs +43 -0
- package/lib/hooks/teammate-idle-guard.mjs +54 -0
- package/lib/hooks/workflow-guard.mjs +62 -0
- package/lib/host-capabilities.mjs +123 -0
- package/lib/init-docs.mjs +382 -0
- package/lib/mcp/server.mjs +1123 -0
- package/lib/mcp-catalog.json +243 -0
- package/lib/mcp-manager.mjs +433 -0
- package/lib/mcp-platform-config.mjs +104 -0
- package/lib/model-router.mjs +810 -0
- package/lib/opencode-config.mjs +44 -0
- package/lib/opencode-runtime-plugin.mjs +909 -0
- package/lib/opencode-telemetry.mjs +433 -0
- package/lib/orchestration-policy.mjs +258 -0
- package/lib/prompt-composer.mjs +196 -0
- package/lib/prompt-metadata.mjs +68 -0
- package/lib/review.mjs +429 -0
- package/lib/role-preload.mjs +52 -0
- package/lib/schemas/decision.json +50 -0
- package/lib/schemas/implementation.json +51 -0
- package/lib/schemas/review-report.json +32 -0
- package/lib/schemas/test-report.json +43 -0
- package/lib/server/index.mjs +334 -0
- package/lib/server/static/app.js +841 -0
- package/lib/server/static/index.html +820 -0
- package/lib/service-manager.mjs +225 -0
- package/lib/setup.mjs +319 -0
- package/lib/status.mjs +707 -0
- package/lib/storage/backend.mjs +44 -0
- package/lib/storage/embeddings.mjs +70 -0
- package/lib/storage/hybrid-query.mjs +184 -0
- package/lib/storage/sql-store.mjs +55 -0
- package/lib/storage/state-source.mjs +101 -0
- package/lib/storage/sync.mjs +164 -0
- package/lib/storage/vector-store.mjs +59 -0
- package/lib/telemetry/backends/langfuse.mjs +58 -0
- package/lib/telemetry/backends/noop.mjs +16 -0
- package/lib/telemetry/langfuse-ingest.mjs +108 -0
- package/lib/telemetry/langfuse-model-sync.mjs +270 -0
- package/lib/telemetry/team-rollup.mjs +143 -0
- package/lib/toolkit-env.mjs +30 -0
- package/lib/validator.mjs +181 -0
- package/lib/workflow-state.mjs +794 -0
- package/package.json +53 -0
- package/personas/construct.md +94 -0
- package/platforms/claude/CLAUDE.md +30 -0
- package/platforms/claude/settings.template.json +472 -0
- package/platforms/opencode/config.template.json +65 -0
- package/platforms/opencode/plugins/construct-fallback.js +5 -0
- package/platforms/opencode/sync-config.mjs +69 -0
- package/rules/common/agents.md +55 -0
- package/rules/common/code-review.md +129 -0
- package/rules/common/coding-style.md +95 -0
- package/rules/common/comments.md +139 -0
- package/rules/common/cx-agent-routing.md +61 -0
- package/rules/common/cx-skill-routing.md +11 -0
- package/rules/common/development-workflow.md +49 -0
- package/rules/common/git-workflow.md +29 -0
- package/rules/common/hooks.md +35 -0
- package/rules/common/patterns.md +36 -0
- package/rules/common/performance.md +71 -0
- package/rules/common/security.md +34 -0
- package/rules/common/testing.md +62 -0
- package/rules/golang/coding-style.md +37 -0
- package/rules/golang/hooks.md +22 -0
- package/rules/golang/patterns.md +50 -0
- package/rules/golang/security.md +39 -0
- package/rules/golang/testing.md +36 -0
- package/rules/python/coding-style.md +47 -0
- package/rules/python/hooks.md +24 -0
- package/rules/python/patterns.md +44 -0
- package/rules/python/security.md +35 -0
- package/rules/python/testing.md +43 -0
- package/rules/swift/coding-style.md +52 -0
- package/rules/swift/hooks.md +25 -0
- package/rules/swift/patterns.md +71 -0
- package/rules/swift/security.md +38 -0
- package/rules/swift/testing.md +50 -0
- package/rules/typescript/coding-style.md +204 -0
- package/rules/typescript/hooks.md +27 -0
- package/rules/typescript/patterns.md +57 -0
- package/rules/typescript/security.md +33 -0
- package/rules/typescript/testing.md +23 -0
- package/rules/web/coding-style.md +101 -0
- package/rules/web/design-quality.md +68 -0
- package/rules/web/hooks.md +125 -0
- package/rules/web/patterns.md +84 -0
- package/rules/web/performance.md +69 -0
- package/rules/web/security.md +62 -0
- package/rules/web/testing.md +60 -0
- package/rules/zh/README.md +113 -0
- package/rules/zh/agents.md +55 -0
- package/rules/zh/code-review.md +129 -0
- package/rules/zh/coding-style.md +53 -0
- package/rules/zh/development-workflow.md +49 -0
- package/rules/zh/git-workflow.md +29 -0
- package/rules/zh/hooks.md +35 -0
- package/rules/zh/patterns.md +36 -0
- package/rules/zh/performance.md +60 -0
- package/rules/zh/security.md +34 -0
- package/rules/zh/testing.md +34 -0
- package/skills/ai/agent-dev.md +102 -0
- package/skills/ai/llm-security.md +105 -0
- package/skills/ai/ml-ops.md +169 -0
- package/skills/ai/orchestration-workflow.md +87 -0
- package/skills/ai/prompt-and-eval.md +114 -0
- package/skills/ai/prompt-optimizer.md +114 -0
- package/skills/ai/rag-system.md +104 -0
- package/skills/architecture/api-design.md +100 -0
- package/skills/architecture/caching.md +101 -0
- package/skills/architecture/cloud-native.md +97 -0
- package/skills/architecture/message-queue.md +100 -0
- package/skills/architecture/security-arch.md +105 -0
- package/skills/development/cpp.md +127 -0
- package/skills/development/go.md +129 -0
- package/skills/development/java.md +134 -0
- package/skills/development/kotlin.md +140 -0
- package/skills/development/mobile-crossplatform.md +144 -0
- package/skills/development/python.md +109 -0
- package/skills/development/rust.md +127 -0
- package/skills/development/shell.md +127 -0
- package/skills/development/swift.md +129 -0
- package/skills/development/typescript.md +129 -0
- package/skills/devops/ci-cd.md +108 -0
- package/skills/devops/containerization.md +106 -0
- package/skills/devops/cost-optimization.md +105 -0
- package/skills/devops/data-engineering.md +181 -0
- package/skills/devops/database.md +95 -0
- package/skills/devops/dependency-management.md +91 -0
- package/skills/devops/devsecops.md +96 -0
- package/skills/devops/git-workflow.md +100 -0
- package/skills/devops/incident-response.md +167 -0
- package/skills/devops/monorepo.md +87 -0
- package/skills/devops/observability.md +103 -0
- package/skills/devops/performance.md +104 -0
- package/skills/devops/testing.md +104 -0
- package/skills/docs/adr-workflow.md +32 -0
- package/skills/docs/backlog-proposal-workflow.md +19 -0
- package/skills/docs/customer-profile-workflow.md +22 -0
- package/skills/docs/evidence-ingest-workflow.md +23 -0
- package/skills/docs/init-docs.md +160 -0
- package/skills/docs/init-project.md +50 -0
- package/skills/docs/prd-workflow.md +57 -0
- package/skills/docs/prfaq-workflow.md +25 -0
- package/skills/docs/product-intelligence-review.md +22 -0
- package/skills/docs/product-intelligence-workflow.md +62 -0
- package/skills/docs/product-signal-workflow.md +27 -0
- package/skills/docs/research-workflow.md +28 -0
- package/skills/docs/runbook-workflow.md +24 -0
- package/skills/exploration/repo-map.md +297 -0
- package/skills/frameworks/django.md +159 -0
- package/skills/frameworks/nextjs.md +148 -0
- package/skills/frameworks/react.md +132 -0
- package/skills/frameworks/spring-boot.md +165 -0
- package/skills/frontend-design/accessibility.md +153 -0
- package/skills/frontend-design/component-patterns.md +111 -0
- package/skills/frontend-design/engineering.md +122 -0
- package/skills/frontend-design/state-management.md +118 -0
- package/skills/frontend-design/ui-aesthetics.md +102 -0
- package/skills/frontend-design/ux-principles.md +126 -0
- package/skills/quality-gates/review-work.md +90 -0
- package/skills/quality-gates/verify-change.md +94 -0
- package/skills/quality-gates/verify-module.md +96 -0
- package/skills/quality-gates/verify-quality.md +93 -0
- package/skills/quality-gates/verify-security.md +95 -0
- package/skills/roles/architect.ai-systems.md +37 -0
- package/skills/roles/architect.data.md +37 -0
- package/skills/roles/architect.enterprise.md +37 -0
- package/skills/roles/architect.integration.md +37 -0
- package/skills/roles/architect.md +68 -0
- package/skills/roles/architect.platform.md +37 -0
- package/skills/roles/data-analyst.experiment.md +37 -0
- package/skills/roles/data-analyst.md +68 -0
- package/skills/roles/data-analyst.product-intelligence.md +37 -0
- package/skills/roles/data-analyst.product.md +37 -0
- package/skills/roles/data-analyst.telemetry.md +37 -0
- package/skills/roles/data-engineer.pipeline.md +37 -0
- package/skills/roles/data-engineer.vector-retrieval.md +37 -0
- package/skills/roles/data-engineer.warehouse.md +37 -0
- package/skills/roles/debugger.md +68 -0
- package/skills/roles/designer.accessibility.md +43 -0
- package/skills/roles/designer.md +68 -0
- package/skills/roles/engineer.ai.md +49 -0
- package/skills/roles/engineer.data.md +49 -0
- package/skills/roles/engineer.md +85 -0
- package/skills/roles/engineer.platform.md +49 -0
- package/skills/roles/operator.docs.md +43 -0
- package/skills/roles/operator.md +68 -0
- package/skills/roles/operator.release.md +43 -0
- package/skills/roles/operator.sre.md +43 -0
- package/skills/roles/orchestrator.md +66 -0
- package/skills/roles/product-manager.ai-product.md +37 -0
- package/skills/roles/product-manager.business-strategy.md +43 -0
- package/skills/roles/product-manager.enterprise.md +37 -0
- package/skills/roles/product-manager.growth.md +37 -0
- package/skills/roles/product-manager.md +67 -0
- package/skills/roles/product-manager.platform.md +37 -0
- package/skills/roles/product-manager.product.md +37 -0
- package/skills/roles/qa.ai-eval.md +37 -0
- package/skills/roles/qa.api-contract.md +37 -0
- package/skills/roles/qa.data-pipeline.md +37 -0
- package/skills/roles/qa.md +68 -0
- package/skills/roles/qa.test-automation.md +49 -0
- package/skills/roles/qa.web-ui.md +37 -0
- package/skills/roles/researcher.explorer.md +43 -0
- package/skills/roles/researcher.md +68 -0
- package/skills/roles/researcher.ux.md +43 -0
- package/skills/roles/reviewer.devil-advocate.md +43 -0
- package/skills/roles/reviewer.evaluator.md +43 -0
- package/skills/roles/reviewer.md +68 -0
- package/skills/roles/reviewer.trace.md +43 -0
- package/skills/roles/security.ai.md +37 -0
- package/skills/roles/security.appsec.md +37 -0
- package/skills/roles/security.cloud.md +37 -0
- package/skills/roles/security.legal-compliance.md +49 -0
- package/skills/roles/security.md +68 -0
- package/skills/roles/security.privacy.md +37 -0
- package/skills/roles/security.supply-chain.md +37 -0
- package/skills/routing.md +139 -0
- package/skills/security/blue-team.md +83 -0
- package/skills/security/code-audit.md +94 -0
- package/skills/security/pentest.md +84 -0
- package/skills/security/red-team.md +81 -0
- package/skills/security/threat-intel.md +89 -0
- package/skills/security/vuln-research.md +87 -0
- package/skills/utility/clean-code.md +165 -0
- package/sync-agents.mjs +899 -0
- package/templates/docs/adr.md +27 -0
- package/templates/docs/backlog-proposal.md +26 -0
- package/templates/docs/customer-profile.md +34 -0
- package/templates/docs/evidence-brief.md +37 -0
- package/templates/docs/incident-report.md +46 -0
- package/templates/docs/memo.md +27 -0
- package/templates/docs/meta-prd.md +56 -0
- package/templates/docs/one-pager.md +24 -0
- package/templates/docs/prd-business.md +61 -0
- package/templates/docs/prd-platform.md +62 -0
- package/templates/docs/prd.md +47 -0
- package/templates/docs/prfaq.md +31 -0
- package/templates/docs/product-intelligence-report.md +31 -0
- package/templates/docs/research-brief.md +29 -0
- package/templates/docs/rfc-platform.md +60 -0
- package/templates/docs/rfc.md +46 -0
- package/templates/docs/runbook.md +33 -0
- package/templates/docs/signal-brief.md +25 -0
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
skills/exploration/repo-map.md — Repo Exploration — Codebase Mapping Playbook — Use this skill when entering an unfamiliar codebase, doing deep investigation wo
|
|
3
|
+
|
|
4
|
+
Use this skill when entering an unfamiliar codebase, doing deep investigation work, or producing a `.cx/codebase-map.md` artifact for future sessions. Agents: `
|
|
5
|
+
-->
|
|
6
|
+
# Repo Exploration — Codebase Mapping Playbook
|
|
7
|
+
|
|
8
|
+
Use this skill when entering an unfamiliar codebase, doing deep investigation work, or producing a `.cx/codebase-map.md` artifact for future sessions.
|
|
9
|
+
|
|
10
|
+
Agents: `cx-explorer` (primary), `cx-debugger` (tracing failures), `cx-architect` (architecture questions)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Phase 1: Orient (5 minutes max)
|
|
15
|
+
|
|
16
|
+
Answer these questions before reading any source files:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
What is this project? → README.md, package.json description, go.mod module name
|
|
20
|
+
What language/runtime? → file extensions, Dockerfile, .tool-versions, .nvmrc
|
|
21
|
+
How do I run it? → Makefile, justfile, package.json scripts, Procfile, README "Quick Start"
|
|
22
|
+
How do I test it? → CI config (.github/workflows/, .circleci/, Jenkinsfile)
|
|
23
|
+
What does it depend on? → package.json/go.mod/Cargo.toml/requirements.txt top-level deps
|
|
24
|
+
How old / active is it? → git log --oneline -10, git shortlog -sn --no-merges | head -5
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Commands:
|
|
28
|
+
```bash
|
|
29
|
+
cat README.md | head -80
|
|
30
|
+
cat package.json 2>/dev/null || cat go.mod 2>/dev/null || cat Cargo.toml 2>/dev/null
|
|
31
|
+
ls -la
|
|
32
|
+
git log --oneline -10
|
|
33
|
+
git shortlog -sn --no-merges | head -5
|
|
34
|
+
find . -name "Makefile" -o -name "justfile" | head -3
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Phase 2: Map the Structure
|
|
40
|
+
|
|
41
|
+
### 2a. Top-level inventory
|
|
42
|
+
```bash
|
|
43
|
+
ls -la # root entries
|
|
44
|
+
find . -maxdepth 2 -type d \
|
|
45
|
+
! -path '*/node_modules/*' \
|
|
46
|
+
! -path '*/.git/*' \
|
|
47
|
+
! -path '*/vendor/*' \
|
|
48
|
+
! -path '*/.next/*' \
|
|
49
|
+
! -path '*/dist/*' \
|
|
50
|
+
! -path '*/__pycache__/*'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Classify each top-level directory as one of:
|
|
54
|
+
- **entry** — main executables, CLIs, servers (cmd/, bin/, app/, main.*)
|
|
55
|
+
- **lib** — shared library code (lib/, pkg/, src/, internal/)
|
|
56
|
+
- **ui** — frontend/views (web/, frontend/, views/, components/)
|
|
57
|
+
- **config** — configuration, env templates (.env.example, config/, etc/)
|
|
58
|
+
- **infra** — deployment, CI/CD, Docker (deploy/, k8s/, .github/, terraform/)
|
|
59
|
+
- **test** — test-only code (test/, tests/, __tests__/, spec/)
|
|
60
|
+
- **docs** — documentation (docs/, .cx/)
|
|
61
|
+
- **generated** — auto-generated, do not read (dist/, build/, .next/, vendor/)
|
|
62
|
+
|
|
63
|
+
### 2b. Entry points
|
|
64
|
+
|
|
65
|
+
Find where execution begins:
|
|
66
|
+
```bash
|
|
67
|
+
# Node/Bun
|
|
68
|
+
cat package.json | python3 -c "import json,sys; p=json.load(sys.stdin); print(p.get('main',''), p.get('scripts',{}))"
|
|
69
|
+
|
|
70
|
+
# Go
|
|
71
|
+
find . -name "main.go" ! -path '*/vendor/*'
|
|
72
|
+
|
|
73
|
+
# Python
|
|
74
|
+
find . -name "__main__.py" -o -name "wsgi.py" -o -name "asgi.py" | head -5
|
|
75
|
+
|
|
76
|
+
# Rust
|
|
77
|
+
grep -r "fn main" --include="*.rs" -l | head -5
|
|
78
|
+
|
|
79
|
+
# Shell
|
|
80
|
+
grep -rl "#!/" --include="*.sh" . | head -5
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 2c. Dependency graph (module level)
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# What imports what?
|
|
87
|
+
# Node — find the most imported internal modules
|
|
88
|
+
grep -rh "from '\.\." --include="*.ts" --include="*.tsx" --include="*.js" . \
|
|
89
|
+
! -path '*/node_modules/*' | sort | uniq -c | sort -rn | head -20
|
|
90
|
+
|
|
91
|
+
# Go
|
|
92
|
+
grep -rh '".*/' --include="*.go" . ! -path '*/vendor/*' \
|
|
93
|
+
| grep -v 'github.com/\|golang.org/' | sort | uniq -c | sort -rn | head -20
|
|
94
|
+
|
|
95
|
+
# Python
|
|
96
|
+
grep -rh "^from \." --include="*.py" . | sort | uniq -c | sort -rn | head -20
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Phase 3: Trace the Hot Paths
|
|
102
|
+
|
|
103
|
+
A "hot path" is the most important flow in the system. For most projects that's one of:
|
|
104
|
+
- **Web API**: HTTP request → middleware → handler → service → DB → response
|
|
105
|
+
- **CLI**: parse args → load config → execute command → output
|
|
106
|
+
- **Worker**: consume queue → process → persist → emit event
|
|
107
|
+
- **UI**: user action → state update → API call → render
|
|
108
|
+
|
|
109
|
+
### Find the hot path:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Largest files (usually core logic, not generated)
|
|
113
|
+
find . -name "*.ts" -o -name "*.go" -o -name "*.py" -o -name "*.rs" \
|
|
114
|
+
! -path '*/node_modules/*' ! -path '*/vendor/*' ! -path '*/dist/*' \
|
|
115
|
+
| xargs wc -l 2>/dev/null | sort -rn | head -20
|
|
116
|
+
|
|
117
|
+
# Most-changed files (highest churn = highest importance)
|
|
118
|
+
git log --format=format: --name-only | grep -v '^$' | sort | uniq -c | sort -rn | head -20
|
|
119
|
+
|
|
120
|
+
# Most-imported files (highest fan-in = highest centrality)
|
|
121
|
+
# (see Phase 2c commands above)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Trace one hot path end to end:
|
|
125
|
+
|
|
126
|
+
1. Pick the most central handler/service file
|
|
127
|
+
2. Read it fully
|
|
128
|
+
3. Follow every dependency one level deep
|
|
129
|
+
4. Stop when you hit: external library call, DB query, external API call, or file I/O
|
|
130
|
+
|
|
131
|
+
Document as: `ENTRY → fn1() → fn2() → fn3() → [DB|API|FS]`
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Phase 4: Identify Conventions
|
|
136
|
+
|
|
137
|
+
Answer these by reading 3–5 files in each category:
|
|
138
|
+
|
|
139
|
+
**Naming**: camelCase? snake_case? PascalCase for types? Consistent file naming?
|
|
140
|
+
|
|
141
|
+
**Error handling**: Throw/catch? Result type? Custom error types? Error logged or propagated?
|
|
142
|
+
|
|
143
|
+
**Testing**: Co-located tests (`*.test.ts`)? Separate `/test` dir? Fixtures? Mocking approach?
|
|
144
|
+
|
|
145
|
+
**Dependencies**: Injected? Global singletons? Module-level init?
|
|
146
|
+
|
|
147
|
+
**Configuration**: Env vars only? Config files? Validation at startup?
|
|
148
|
+
|
|
149
|
+
**Auth pattern**: Middleware? Guard functions? Where are permissions enforced?
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Find test files
|
|
153
|
+
find . -name "*.test.*" -o -name "*.spec.*" ! -path '*/node_modules/*' | head -20
|
|
154
|
+
find . -path '*/test*' -name "*.go" | head -10
|
|
155
|
+
|
|
156
|
+
# Find error types / custom errors
|
|
157
|
+
grep -rl "class.*Error\|type.*Error\|errors.New\|fmt.Errorf" --include="*.ts" --include="*.go" . \
|
|
158
|
+
! -path '*/node_modules/*' | head -10
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Phase 5: Detect Debt and Gaps
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# TODOs and FIXMEs (volume = debt signal)
|
|
167
|
+
grep -rn "TODO\|FIXME\|HACK\|XXX\|NOSONAR" \
|
|
168
|
+
! -path '*/node_modules/*' ! -path '*/.git/*' | wc -l
|
|
169
|
+
|
|
170
|
+
grep -rn "TODO\|FIXME\|HACK" \
|
|
171
|
+
! -path '*/node_modules/*' ! -path '*/.git/*' | head -20
|
|
172
|
+
|
|
173
|
+
# Commented-out code
|
|
174
|
+
grep -rn "^[[:space:]]*//.*[a-zA-Z].*[a-zA-Z]" --include="*.ts" --include="*.go" . \
|
|
175
|
+
! -path '*/node_modules/*' | grep -v "http\|Copyright\|License" | head -20
|
|
176
|
+
|
|
177
|
+
# Missing test coverage signals
|
|
178
|
+
find . -name "*.ts" ! -name "*.test.ts" ! -name "*.d.ts" ! -path '*/node_modules/*' \
|
|
179
|
+
| while read f; do
|
|
180
|
+
base="${f%.ts}"
|
|
181
|
+
[ ! -f "${base}.test.ts" ] && echo "no test: $f"
|
|
182
|
+
done | head -20
|
|
183
|
+
|
|
184
|
+
# Stale dependencies
|
|
185
|
+
npm outdated 2>/dev/null | head -20
|
|
186
|
+
go list -m -u all 2>/dev/null | grep '\[' | head -20
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Phase 6: Produce the Map
|
|
192
|
+
|
|
193
|
+
Write `.cx/codebase-map.md` in the project root using this template:
|
|
194
|
+
|
|
195
|
+
```markdown
|
|
196
|
+
# Codebase Map — {project-name}
|
|
197
|
+
|
|
198
|
+
Generated: {date}
|
|
199
|
+
Mapped by: cx-explorer
|
|
200
|
+
|
|
201
|
+
## Overview
|
|
202
|
+
{1-3 sentences: what this is, what it does, who uses it}
|
|
203
|
+
|
|
204
|
+
## Tech Stack
|
|
205
|
+
- Runtime: {language + version}
|
|
206
|
+
- Framework: {main framework}
|
|
207
|
+
- Database: {DB + ORM if any}
|
|
208
|
+
- Key deps: {3-5 most important libraries}
|
|
209
|
+
- Test framework: {test runner}
|
|
210
|
+
|
|
211
|
+
## Structure
|
|
212
|
+
| Directory | Role |
|
|
213
|
+
|---|---|
|
|
214
|
+
| `cmd/` | Entry points — CLI commands |
|
|
215
|
+
| `internal/` | Core domain logic |
|
|
216
|
+
| `pkg/` | Shared libraries |
|
|
217
|
+
| ... | ... |
|
|
218
|
+
|
|
219
|
+
## Entry Points
|
|
220
|
+
- `{file}:{function}` — {what triggers it, e.g. "HTTP server start"}
|
|
221
|
+
- `{file}:{function}` — {e.g. "CLI entrypoint"}
|
|
222
|
+
|
|
223
|
+
## Hot Paths
|
|
224
|
+
### {Primary flow name, e.g. "API Request → Response"}
|
|
225
|
+
`handler.ts:handleRequest` → `service.ts:processRequest` → `db.ts:query` → response
|
|
226
|
+
|
|
227
|
+
### {Secondary flow if applicable}
|
|
228
|
+
...
|
|
229
|
+
|
|
230
|
+
## Key Conventions
|
|
231
|
+
- **Errors**: {how errors are handled}
|
|
232
|
+
- **Config**: {how config is loaded}
|
|
233
|
+
- **Auth**: {where auth is enforced}
|
|
234
|
+
- **Testing**: {test file location + approach}
|
|
235
|
+
- **Naming**: {naming conventions observed}
|
|
236
|
+
|
|
237
|
+
## Files to Know
|
|
238
|
+
| File | Why It Matters |
|
|
239
|
+
|---|---|
|
|
240
|
+
| `{path}` | {e.g. "Central router — all HTTP routes defined here"} |
|
|
241
|
+
| `{path}` | {e.g. "DB connection pool — touch before any DB work"} |
|
|
242
|
+
| `{path}` | {e.g. "Auth middleware — all protected routes pass through here"} |
|
|
243
|
+
|
|
244
|
+
## Debt + Watch Areas
|
|
245
|
+
- {TODO/FIXME count}: {N} open TODOs, concentrated in {area}
|
|
246
|
+
- {Testing gap}: {which modules lack test coverage}
|
|
247
|
+
- {Outdated deps}: {specific dep names if notable}
|
|
248
|
+
- {Other}: {anything surprising or risky}
|
|
249
|
+
|
|
250
|
+
## What to Read First
|
|
251
|
+
If you're about to {do X}, start with: {file or path}
|
|
252
|
+
If you're about to {do Y}, start with: {file or path}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Quick Reference — Useful One-Liners
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
# File count by extension
|
|
261
|
+
find . ! -path '*/node_modules/*' ! -path '*/.git/*' -type f \
|
|
262
|
+
| sed 's/.*\.//' | sort | uniq -c | sort -rn | head -15
|
|
263
|
+
|
|
264
|
+
# Largest directories
|
|
265
|
+
du -sh */ 2>/dev/null | sort -rh | head -10
|
|
266
|
+
|
|
267
|
+
# Recent hot files (changed in last 30 days)
|
|
268
|
+
git log --since="30 days ago" --format=format: --name-only \
|
|
269
|
+
| grep -v '^$' | sort | uniq -c | sort -rn | head -20
|
|
270
|
+
|
|
271
|
+
# Who knows this codebase
|
|
272
|
+
git shortlog -sn --no-merges | head -10
|
|
273
|
+
|
|
274
|
+
# Find config/env loading
|
|
275
|
+
grep -rn "process.env\|os.Getenv\|os.environ\|dotenv" \
|
|
276
|
+
! -path '*/node_modules/*' -l | head -10
|
|
277
|
+
|
|
278
|
+
# Find all HTTP routes
|
|
279
|
+
grep -rn "router\.\|app\.get\|app\.post\|http\.HandleFunc\|@Get\|@Post" \
|
|
280
|
+
! -path '*/node_modules/*' | head -20
|
|
281
|
+
|
|
282
|
+
# Find DB schema / models
|
|
283
|
+
find . -name "schema.*" -o -name "models.*" -o -name "*.prisma" \
|
|
284
|
+
-o -name "*_migration*" ! -path '*/node_modules/*' | head -10
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Agent Handoffs
|
|
290
|
+
|
|
291
|
+
After producing `.cx/codebase-map.md`:
|
|
292
|
+
|
|
293
|
+
- **Explain architecture decisions** → `cx-architect`
|
|
294
|
+
- **Trace a specific failure** → `cx-debugger` (provide the codebase-map as context)
|
|
295
|
+
- **Check security posture** → `cx-security` (highlight auth files from the map)
|
|
296
|
+
- **Assess test coverage** → `cx-qa` (provide the files-to-know list)
|
|
297
|
+
- **Understand a library used** → `cx-docs-researcher` (provide the dep name)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
skills/frameworks/django.md — Django — ```
|
|
3
|
+
|
|
4
|
+
## Project Structure ```
|
|
5
|
+
-->
|
|
6
|
+
# Django
|
|
7
|
+
|
|
8
|
+
## Project Structure
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
project/
|
|
12
|
+
├── config/ ← Django settings package
|
|
13
|
+
│ ├── settings/
|
|
14
|
+
│ │ ├── base.py
|
|
15
|
+
│ │ ├── local.py
|
|
16
|
+
│ │ └── production.py
|
|
17
|
+
│ ├── urls.py
|
|
18
|
+
│ └── wsgi.py
|
|
19
|
+
├── apps/
|
|
20
|
+
│ ├── users/ ← Feature-bounded app
|
|
21
|
+
│ │ ├── models.py
|
|
22
|
+
│ │ ├── views.py
|
|
23
|
+
│ │ ├── serializers.py
|
|
24
|
+
│ │ ├── urls.py
|
|
25
|
+
│ │ └── tests/
|
|
26
|
+
│ └── items/
|
|
27
|
+
├── manage.py
|
|
28
|
+
└── requirements/
|
|
29
|
+
├── base.txt
|
|
30
|
+
├── local.txt
|
|
31
|
+
└── production.txt
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Keep apps small and feature-bounded. Do not put everything in one app.
|
|
35
|
+
|
|
36
|
+
## Models
|
|
37
|
+
|
|
38
|
+
### Field choices
|
|
39
|
+
|
|
40
|
+
- `CharField` / `TextField` — strings; always set `blank=False` unless optional
|
|
41
|
+
- `UUIDField(default=uuid.uuid4, primary_key=True)` — preferred over auto-increment for external-facing IDs
|
|
42
|
+
- `JSONField` — use sparingly; prefer normalized columns for queryable data
|
|
43
|
+
- `select_related` for FK, `prefetch_related` for M2M — avoid N+1 queries
|
|
44
|
+
|
|
45
|
+
### Migrations
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
python manage.py makemigrations --check # CI gate — fail if migrations needed
|
|
49
|
+
python manage.py migrate --plan # Preview before applying
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- Never edit applied migrations; create new ones
|
|
53
|
+
- For large tables, use `RunSQL` with `CONCURRENTLY` for index additions in production
|
|
54
|
+
- Zero-downtime: add nullable column → deploy → backfill → add constraint → deploy
|
|
55
|
+
|
|
56
|
+
### Model managers
|
|
57
|
+
|
|
58
|
+
Encapsulate query logic in managers, not views:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
class PublishedManager(models.Manager):
|
|
62
|
+
def get_queryset(self):
|
|
63
|
+
return super().get_queryset().filter(status='published')
|
|
64
|
+
|
|
65
|
+
class Item(models.Model):
|
|
66
|
+
objects = models.Manager()
|
|
67
|
+
published = PublishedManager()
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Views
|
|
71
|
+
|
|
72
|
+
### Prefer Class-Based Views (CBV) for standard CRUD
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
class ItemDetailView(LoginRequiredMixin, DetailView):
|
|
76
|
+
model = Item
|
|
77
|
+
template_name = 'items/detail.html'
|
|
78
|
+
context_object_name = 'item'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Use function-based views for one-off logic that doesn't fit CBV patterns.
|
|
82
|
+
|
|
83
|
+
### Django REST Framework (DRF)
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
class ItemViewSet(viewsets.ModelViewSet):
|
|
87
|
+
queryset = Item.objects.select_related('owner')
|
|
88
|
+
serializer_class = ItemSerializer
|
|
89
|
+
permission_classes = [IsAuthenticated]
|
|
90
|
+
filterset_fields = ['status']
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Routers auto-wire CRUD endpoints:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
router = DefaultRouter()
|
|
97
|
+
router.register('items', ItemViewSet)
|
|
98
|
+
urlpatterns = [path('api/', include(router.urls))]
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Serializer validation
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
class ItemSerializer(serializers.ModelSerializer):
|
|
105
|
+
class Meta:
|
|
106
|
+
model = Item
|
|
107
|
+
fields = ['id', 'title', 'status']
|
|
108
|
+
read_only_fields = ['id']
|
|
109
|
+
|
|
110
|
+
def validate_title(self, value):
|
|
111
|
+
if len(value) < 3:
|
|
112
|
+
raise serializers.ValidationError('Title too short.')
|
|
113
|
+
return value
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Security
|
|
117
|
+
|
|
118
|
+
- `SECRET_KEY` from env — never commit
|
|
119
|
+
- `ALLOWED_HOSTS` locked down in production
|
|
120
|
+
- `DEBUG = False` in production (template errors expose internals)
|
|
121
|
+
- CSRF: enabled by default for form views; DRF uses `SessionAuthentication` + CSRF for browser clients
|
|
122
|
+
- `django-environ` or `python-decouple` for settings from environment variables
|
|
123
|
+
- Content security policy: `django-csp` middleware
|
|
124
|
+
- SQL: always use ORM or parameterized `raw()` — never string-format user input into queries
|
|
125
|
+
|
|
126
|
+
## Testing
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
class ItemAPITest(APITestCase):
|
|
130
|
+
def setUp(self):
|
|
131
|
+
self.user = User.objects.create_user(username='tester', password='pass')
|
|
132
|
+
self.client.force_authenticate(self.user)
|
|
133
|
+
|
|
134
|
+
def test_create_item(self):
|
|
135
|
+
resp = self.client.post('/api/items/', {'title': 'New Item'})
|
|
136
|
+
self.assertEqual(resp.status_code, 201)
|
|
137
|
+
self.assertEqual(Item.objects.count(), 1)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
- Use `APITestCase` (DRF) for API tests — wraps each test in a transaction that rolls back
|
|
141
|
+
- `factory_boy` for fixtures — more maintainable than raw `create()`
|
|
142
|
+
- `pytest-django` with `@pytest.mark.django_db` for pytest-style tests
|
|
143
|
+
- `django-silk` or `django-debug-toolbar` for query profiling in development
|
|
144
|
+
|
|
145
|
+
## Performance
|
|
146
|
+
|
|
147
|
+
- Database: add `db_index=True` for filtered columns; `select_related`/`prefetch_related` to eliminate N+1
|
|
148
|
+
- Caching: `django.core.cache` with Redis backend (`django-redis`)
|
|
149
|
+
- Async views: `async def` views supported in Django 4.1+ — use for I/O-bound operations with `asyncio`
|
|
150
|
+
- Task queues: `Celery` + Redis/RabbitMQ for background jobs; `django-celery-beat` for scheduling
|
|
151
|
+
- `gunicorn` + `uvicorn` workers for async support in production
|
|
152
|
+
|
|
153
|
+
## Common Pitfalls
|
|
154
|
+
|
|
155
|
+
- `objects.all()` in views without pagination — always use `Paginator` or DRF `pagination_class`
|
|
156
|
+
- Accessing related objects in a loop without `select_related` — profile with `django-debug-toolbar`
|
|
157
|
+
- `settings.DEBUG` checks in production-like environments — use environment-specific settings modules
|
|
158
|
+
- File uploads to local storage in production — use `django-storages` with S3/GCS
|
|
159
|
+
- Signals for business logic — prefer explicit service functions; signals are invisible and hard to test
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
skills/frameworks/nextjs.md — Next.js (App Router) — ```
|
|
3
|
+
|
|
4
|
+
## App Router Mental Model ```
|
|
5
|
+
-->
|
|
6
|
+
# Next.js (App Router)
|
|
7
|
+
|
|
8
|
+
## App Router Mental Model
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
app/
|
|
12
|
+
├── layout.tsx ← Root layout — wraps every page
|
|
13
|
+
├── page.tsx ← / route
|
|
14
|
+
├── (auth)/ ← Route group (no URL segment)
|
|
15
|
+
│ ├── login/page.tsx ← /login
|
|
16
|
+
│ └── register/page.tsx
|
|
17
|
+
├── dashboard/
|
|
18
|
+
│ ├── layout.tsx ← Nested layout for /dashboard/*
|
|
19
|
+
│ └── page.tsx ← /dashboard
|
|
20
|
+
└── api/
|
|
21
|
+
└── items/route.ts ← /api/items (Route Handler)
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Key rules:
|
|
25
|
+
- `page.tsx` = publicly accessible route segment
|
|
26
|
+
- `layout.tsx` = persistent shell across sibling pages
|
|
27
|
+
- `loading.tsx` = automatic Suspense boundary while segment loads
|
|
28
|
+
- `error.tsx` = error boundary for the segment
|
|
29
|
+
- `not-found.tsx` = 404 for the segment
|
|
30
|
+
|
|
31
|
+
## Data Fetching
|
|
32
|
+
|
|
33
|
+
### Server Components fetch directly
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
// app/items/page.tsx
|
|
37
|
+
async function ItemsPage() {
|
|
38
|
+
const items = await fetch('https://api.example.com/items', {
|
|
39
|
+
next: { revalidate: 60 } // ISR: revalidate every 60s
|
|
40
|
+
}).then(r => r.json());
|
|
41
|
+
return <ItemList items={items} />;
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Caching behaviors:
|
|
46
|
+
|
|
47
|
+
| Option | Behavior |
|
|
48
|
+
|---|---|
|
|
49
|
+
| `cache: 'force-cache'` | Static — cache forever (default) |
|
|
50
|
+
| `next: { revalidate: N }` | ISR — revalidate after N seconds |
|
|
51
|
+
| `cache: 'no-store'` | Dynamic — always fresh |
|
|
52
|
+
| `next: { tags: ['items'] }` | Tag for on-demand revalidation |
|
|
53
|
+
|
|
54
|
+
### On-demand revalidation
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// Server Action or API Route
|
|
58
|
+
import { revalidateTag } from 'next/cache';
|
|
59
|
+
revalidateTag('items'); // invalidates all fetches tagged 'items'
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Route Handlers (API Routes replacement)
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
// app/api/items/route.ts
|
|
66
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
67
|
+
|
|
68
|
+
export async function GET(req: NextRequest) {
|
|
69
|
+
const items = await db.items.findMany();
|
|
70
|
+
return NextResponse.json(items);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Server Actions
|
|
75
|
+
|
|
76
|
+
Mutate data from Client Components without a separate API route:
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
// app/actions.ts
|
|
80
|
+
'use server';
|
|
81
|
+
export async function createItem(formData: FormData) {
|
|
82
|
+
const title = formData.get('title') as string;
|
|
83
|
+
await db.items.create({ data: { title } });
|
|
84
|
+
revalidatePath('/items');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Client Component
|
|
88
|
+
<form action={createItem}>
|
|
89
|
+
<input name="title" />
|
|
90
|
+
<button>Create</button>
|
|
91
|
+
</form>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Validate Server Action inputs — they are network endpoints.
|
|
95
|
+
|
|
96
|
+
## Rendering Strategies
|
|
97
|
+
|
|
98
|
+
| Strategy | When |
|
|
99
|
+
|---|---|
|
|
100
|
+
| Static (SSG) | Marketing pages, docs — no user-specific data |
|
|
101
|
+
| ISR | Listings, product pages — stale-ok, periodic refresh |
|
|
102
|
+
| Dynamic (SSR) | Dashboards, auth-gated pages — always fresh |
|
|
103
|
+
| Client | Highly interactive UIs, real-time, after-hydration only |
|
|
104
|
+
|
|
105
|
+
Prefer static/ISR by default; reach for dynamic only when the data must be per-request.
|
|
106
|
+
|
|
107
|
+
## Metadata & SEO
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
// Static
|
|
111
|
+
export const metadata: Metadata = { title: 'Items', description: '...' };
|
|
112
|
+
|
|
113
|
+
// Dynamic
|
|
114
|
+
export async function generateMetadata({ params }: Props): Promise<Metadata> {
|
|
115
|
+
const item = await fetchItem(params.id);
|
|
116
|
+
return { title: item.title };
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Middleware
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
// middleware.ts (runs at the edge before the request)
|
|
124
|
+
export function middleware(req: NextRequest) {
|
|
125
|
+
if (!req.cookies.get('session')) {
|
|
126
|
+
return NextResponse.redirect(new URL('/login', req.url));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
export const config = { matcher: ['/dashboard/:path*'] };
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Middleware runs on the Edge Runtime — no Node.js APIs. Keep it fast; no DB calls.
|
|
133
|
+
|
|
134
|
+
## Performance
|
|
135
|
+
|
|
136
|
+
- Enable Partial Prerendering (PPR) in Next.js 15 for shell + streaming content
|
|
137
|
+
- Use `next/image` for all images — automatic WebP, lazy loading, CLS prevention
|
|
138
|
+
- Use `next/font` for self-hosted fonts — eliminates FOUT and external requests
|
|
139
|
+
- Bundle analysis: `ANALYZE=true next build`
|
|
140
|
+
- Streaming: wrap slow data-dependent sections in `<Suspense>`
|
|
141
|
+
|
|
142
|
+
## Common Pitfalls
|
|
143
|
+
|
|
144
|
+
- Importing client-only code (browser APIs, hooks) in Server Components — add `'use client'`
|
|
145
|
+
- Large `layout.tsx` re-renders — use `memo` on stable child subtrees
|
|
146
|
+
- Fetching the same data in multiple components — hoist to the nearest shared ancestor Server Component (fetch is deduplicated within a request)
|
|
147
|
+
- Dynamic routes missing `generateStaticParams` for static builds — causes runtime 404
|
|
148
|
+
- Server Actions called without input validation — treat as untrusted user input
|