@1aboveio/skills 0.0.0-stage → 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/README.md +30 -2
- package/bin/cli.mjs +14 -0
- package/bin/select-core.mjs +172 -0
- package/package.json +146 -4
- package/skills/app-dev/airflow/LICENSE +3 -0
- package/skills/app-dev/airflow/SKILL.md +199 -0
- package/skills/app-dev/airflow/release-check.mjs +93 -0
- package/skills/app-dev/android-foundation/LICENSE +3 -0
- package/skills/app-dev/android-foundation/SKILL.md +192 -0
- package/skills/app-dev/android-foundation/assets/android-ci-job.yml +217 -0
- package/skills/app-dev/android-foundation/references/ci.md +87 -0
- package/skills/app-dev/android-foundation/references/gotchas.md +221 -0
- package/skills/app-dev/android-foundation/references/setup.md +164 -0
- package/skills/app-dev/android-foundation/release-check.mjs +93 -0
- package/skills/app-dev/android-foundation/scripts/device-run.sh +176 -0
- package/skills/app-dev/android-foundation/scripts/device-run.test.mjs +172 -0
- package/skills/app-dev/app-debug/LICENSE +3 -0
- package/skills/app-dev/app-debug/SKILL.md +110 -0
- package/skills/app-dev/app-debug/references/common-errors.md +128 -0
- package/skills/app-dev/app-debug/release-check.mjs +93 -0
- package/skills/app-dev/better-auth/LICENSE +3 -0
- package/skills/app-dev/better-auth/SKILL.md +598 -0
- package/skills/app-dev/better-auth/references/feishu-api.md +270 -0
- package/skills/app-dev/better-auth/release-check.mjs +93 -0
- package/skills/app-dev/data-catalog/LICENSE +3 -0
- package/skills/app-dev/data-catalog/SKILL.md +204 -0
- package/skills/app-dev/data-catalog/agents/openai.yaml +3 -0
- package/skills/app-dev/data-catalog/references/data-catalog-conventions.md +75 -0
- package/skills/app-dev/data-catalog/references/field-definitions.md +116 -0
- package/skills/app-dev/data-catalog/references/format.md +121 -0
- package/skills/app-dev/data-catalog/release-check.mjs +93 -0
- package/skills/app-dev/data-catalog/scripts/data-catalog.test.mjs +36 -0
- package/skills/app-dev/data-catalog/scripts/data_catalog.py +1392 -0
- package/skills/app-dev/data-catalog/scripts/persist-conventions-core.mjs +117 -0
- package/skills/app-dev/data-catalog/scripts/persist-conventions.mjs +17 -0
- package/skills/app-dev/data-catalog/scripts/test_data_catalog.py +571 -0
- package/skills/app-dev/ios-foundation/LICENSE +3 -0
- package/skills/app-dev/ios-foundation/SKILL.md +184 -0
- package/skills/app-dev/ios-foundation/references/setup.md +243 -0
- package/skills/app-dev/ios-foundation/release-check.mjs +93 -0
- package/skills/app-dev/monorepo/LICENSE +3 -0
- package/skills/app-dev/monorepo/SKILL.md +462 -0
- package/skills/app-dev/monorepo/release-check.mjs +93 -0
- package/skills/app-dev/nextjs-fullstack/LICENSE +3 -0
- package/skills/app-dev/nextjs-fullstack/SKILL.md +211 -0
- package/skills/app-dev/nextjs-fullstack/conventions.md +318 -0
- package/skills/app-dev/nextjs-fullstack/frontend-conventions.md +61 -0
- package/skills/app-dev/nextjs-fullstack/nextjs16.md +287 -0
- package/skills/app-dev/nextjs-fullstack/release-check.mjs +93 -0
- package/skills/app-dev/nextjs-fullstack/server-actions.md +409 -0
- package/skills/app-dev/prisma-setup/LICENSE +3 -0
- package/skills/app-dev/prisma-setup/SKILL.md +181 -0
- package/skills/app-dev/prisma-setup/nextjs.md +258 -0
- package/skills/app-dev/prisma-setup/release-check.mjs +93 -0
- package/skills/app-dev/prisma-setup/turborepo.md +301 -0
- package/skills/app-dev/pyspark/LICENSE +3 -0
- package/skills/app-dev/pyspark/SKILL.md +127 -0
- package/skills/app-dev/pyspark/assets/templates/etl.py +748 -0
- package/skills/app-dev/pyspark/assets/templates/utils/__init__.py +1 -0
- package/skills/app-dev/pyspark/assets/templates/utils/hudi_metadata.py +14 -0
- package/skills/app-dev/pyspark/references/diagnosis-and-profiling.md +169 -0
- package/skills/app-dev/pyspark/references/etl-contract.md +129 -0
- package/skills/app-dev/pyspark/references/production-validation.md +131 -0
- package/skills/app-dev/pyspark/references/reconciliation.md +38 -0
- package/skills/app-dev/pyspark/references/transformation-design.md +190 -0
- package/skills/app-dev/pyspark/references/velocity-feature-calculation.md +193 -0
- package/skills/app-dev/pyspark/release-check.mjs +93 -0
- package/skills/app-dev/pyspark/scripts/spark_eventlog_summary.py +223 -0
- package/skills/app-dev/python-backend/LICENSE +3 -0
- package/skills/app-dev/python-backend/SKILL.md +325 -0
- package/skills/app-dev/python-backend/assets/uv-install.sh +48 -0
- package/skills/app-dev/python-backend/references/uv-installs.md +83 -0
- package/skills/app-dev/python-backend/release-check.mjs +93 -0
- package/skills/app-dev/shadcn/LICENSE +3 -0
- package/skills/app-dev/shadcn/SKILL.md +120 -0
- package/skills/app-dev/shadcn/assets/shadcn-small.png +0 -0
- package/skills/app-dev/shadcn/assets/shadcn.png +0 -0
- package/skills/app-dev/shadcn/cli.md +411 -0
- package/skills/app-dev/shadcn/customization.md +224 -0
- package/skills/app-dev/shadcn/mcp.md +101 -0
- package/skills/app-dev/shadcn/release-check.mjs +93 -0
- package/skills/app-dev/shadcn/rules/base-vs-radix.md +323 -0
- package/skills/app-dev/shadcn/rules/component-selection.md +67 -0
- package/skills/app-dev/shadcn/rules/composition.md +195 -0
- package/skills/app-dev/shadcn/rules/data-table.md +201 -0
- package/skills/app-dev/shadcn/rules/forms.md +255 -0
- package/skills/app-dev/shadcn/rules/icons.md +103 -0
- package/skills/app-dev/shadcn/rules/styling.md +167 -0
- package/skills/app-dev/zod-v4/LICENSE +3 -0
- package/skills/app-dev/zod-v4/SKILL.md +286 -0
- package/skills/app-dev/zod-v4/release-check.mjs +93 -0
- package/skills/cicd/cloud-build/LICENSE +3 -0
- package/skills/cicd/cloud-build/SKILL.md +707 -0
- package/skills/cicd/cloud-build/release-check.mjs +93 -0
- package/skills/cicd/cloud-debug/LICENSE +3 -0
- package/skills/cicd/cloud-debug/SKILL.md +315 -0
- package/skills/cicd/cloud-debug/references/build-failures.md +238 -0
- package/skills/cicd/cloud-debug/references/deploy-failures.md +376 -0
- package/skills/cicd/cloud-debug/references/pipeline-failures.md +378 -0
- package/skills/cicd/cloud-debug/release-check.mjs +93 -0
- package/skills/cicd/cloud-deploy/LICENSE +3 -0
- package/skills/cicd/cloud-deploy/SKILL.md +230 -0
- package/skills/cicd/cloud-deploy/references/config-templates.md +257 -0
- package/skills/cicd/cloud-deploy/release-check.mjs +93 -0
- package/skills/cicd/docker/LICENSE +3 -0
- package/skills/cicd/docker/SKILL.md +151 -0
- package/skills/cicd/docker/release-check.mjs +93 -0
- package/skills/cicd/github-actions/LICENSE +3 -0
- package/skills/cicd/github-actions/SKILL.md +111 -0
- package/skills/cicd/github-actions/references/audit-profile-optimize.md +150 -0
- package/skills/cicd/github-actions/references/ci-case-studies.md +141 -0
- package/skills/cicd/github-actions/references/conditional-ci.md +214 -0
- package/skills/cicd/github-actions/references/debugging.md +13 -0
- package/skills/cicd/github-actions/references/pipeline.md +87 -0
- package/skills/cicd/github-actions/references/post-deploy-and-publishing.md +33 -0
- package/skills/cicd/github-actions/references/runners.md +253 -0
- package/skills/cicd/github-actions/references/security.md +29 -0
- package/skills/cicd/github-actions/references/speed-and-audit.md +115 -0
- package/skills/cicd/github-actions/references/two-pass-reading.md +92 -0
- package/skills/cicd/github-actions/release-check.mjs +93 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit-core.mjs +612 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit.mjs +4 -0
- package/skills/cicd/github-actions/scripts/ci-run-audit.test.mjs +637 -0
- package/skills/cicd/github-flow/LICENSE +3 -0
- package/skills/cicd/github-flow/SKILL.md +123 -0
- package/skills/cicd/github-flow/references/ci-conventions.md +14 -0
- package/skills/cicd/github-flow/release-check.mjs +93 -0
- package/skills/cicd/github-flow/scripts/flow-core.mjs +105 -0
- package/skills/cicd/github-flow/scripts/flow.mjs +81 -0
- package/skills/cicd/github-flow/scripts/flow.test.mjs +114 -0
- package/skills/cicd/github-flow/scripts/persist-conventions-core.mjs +117 -0
- package/skills/cicd/github-flow/scripts/persist-conventions.mjs +49 -0
- package/skills/cicd/github-flow/scripts/persist-conventions.test.mjs +108 -0
- package/skills/cicd/google-cloud/LICENSE +3 -0
- package/skills/cicd/google-cloud/SKILL.md +119 -0
- package/skills/cicd/google-cloud/references/gcs.md +469 -0
- package/skills/cicd/google-cloud/references/iam.md +451 -0
- package/skills/cicd/google-cloud/references/project.md +349 -0
- package/skills/cicd/google-cloud/references/secrets.md +336 -0
- package/skills/cicd/google-cloud/references/vpc.md +312 -0
- package/skills/cicd/google-cloud/release-check.mjs +93 -0
- package/skills/cicd/google-cloud/scripts/create-sa.sh +36 -0
- package/skills/cicd/google-cloud/scripts/gcp-config.sh +31 -0
- package/skills/cicd/google-cloud/scripts/grant-iap.sh +41 -0
- package/skills/cicd/google-cloud/scripts/setup-secrets.sh +48 -0
- package/skills/cicd/mergify/LICENSE +3 -0
- package/skills/cicd/mergify/SKILL.md +102 -0
- package/skills/cicd/mergify/assets/templates/mergify.yml +215 -0
- package/skills/cicd/mergify/assets/templates/ruleset.json +46 -0
- package/skills/cicd/mergify/references/branch-protection.md +282 -0
- package/skills/cicd/mergify/references/configuration.md +274 -0
- package/skills/cicd/mergify/references/diagnosis.md +109 -0
- package/skills/cicd/mergify/references/stacks.md +84 -0
- package/skills/cicd/mergify/references/traps.md +119 -0
- package/skills/cicd/mergify/references/watch-contract.md +274 -0
- package/skills/cicd/mergify/release-check.mjs +93 -0
- package/skills/cicd/mergify/scripts/audit-core.mjs +208 -0
- package/skills/cicd/mergify/scripts/audit.mjs +4 -0
- package/skills/cicd/mergify/scripts/audit.test.mjs +201 -0
- package/skills/cicd/mergify/scripts/entrypoints.test.mjs +106 -0
- package/skills/cicd/mergify/scripts/pr-620-mergify-comments.fixture.json +30 -0
- package/skills/cicd/mergify/scripts/stack-push-core.mjs +258 -0
- package/skills/cicd/mergify/scripts/stack-push.mjs +4 -0
- package/skills/cicd/mergify/scripts/stack-push.test.mjs +233 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery-core.mjs +1065 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery.mjs +4 -0
- package/skills/cicd/mergify/scripts/watch-pr-delivery.test.mjs +1826 -0
- package/skills/cicd/podman/LICENSE +3 -0
- package/skills/cicd/podman/SKILL.md +71 -0
- package/skills/cicd/podman/agents/openai.yaml +4 -0
- package/skills/cicd/podman/assets/templates/podman-compose-socket-directory.yml +6 -0
- package/skills/cicd/podman/assets/templates/podman-service-override.conf +3 -0
- package/skills/cicd/podman/references/compose-compatibility.md +70 -0
- package/skills/cicd/podman/references/networking-and-ports.md +74 -0
- package/skills/cicd/podman/references/rootless-services-and-sockets.md +156 -0
- package/skills/cicd/podman/references/troubleshooting.md +98 -0
- package/skills/cicd/podman/release-check.mjs +93 -0
- package/skills/content/article-review/LICENSE +3 -0
- package/skills/content/article-review/SKILL.md +66 -0
- package/skills/content/article-review/references/report-format.md +68 -0
- package/skills/content/article-review/references/template-guide.md +79 -0
- package/skills/content/article-review/references/template-wechat-payments.md +125 -0
- package/skills/content/article-review/release-check.mjs +93 -0
- package/skills/content/article-to-image/LICENSE +3 -0
- package/skills/content/article-to-image/SKILL.md +91 -0
- package/skills/content/article-to-image/references/formats.md +53 -0
- package/skills/content/article-to-image/release-check.mjs +93 -0
- package/skills/content/flowchart-svg/LICENSE +3 -0
- package/skills/content/flowchart-svg/SKILL.md +43 -0
- package/skills/content/flowchart-svg/release-check.mjs +93 -0
- package/skills/content/flowchart-svg/scripts/export_png.sh +8 -0
- package/skills/content/image-gen/LICENSE +3 -0
- package/skills/content/image-gen/SKILL.md +192 -0
- package/skills/content/image-gen/release-check.mjs +93 -0
- package/skills/content/image-gen/scripts/credentials.mjs +217 -0
- package/skills/content/image-gen/scripts/credentials.test.mjs +212 -0
- package/skills/content/image-gen/scripts/generate.mjs +240 -0
- package/skills/content/image-gen/scripts/options.mjs +293 -0
- package/skills/content/image-gen/scripts/options.test.mjs +245 -0
- package/skills/content/mermaid/LICENSE +3 -0
- package/skills/content/mermaid/SKILL.md +635 -0
- package/skills/content/mermaid/release-check.mjs +93 -0
- package/skills/content/wechat-article-writer/LICENSE +3 -0
- package/skills/content/wechat-article-writer/SKILL.md +92 -0
- package/skills/content/wechat-article-writer/references/style-selector.md +133 -0
- package/skills/content/wechat-article-writer/references/writing-rules.md +152 -0
- package/skills/content/wechat-article-writer/release-check.mjs +93 -0
- package/skills/content/wechat-article-writer/templates/wechat-comparison.md +52 -0
- package/skills/content/wechat-article-writer/templates/wechat-howto.md +51 -0
- package/skills/content/wechat-article-writer/templates/wechat-insight.md +50 -0
- package/skills/content/wechat-article-writer/templates/wechat-pitfall.md +52 -0
- package/skills/content/wechat-publisher/LICENSE +3 -0
- package/skills/content/wechat-publisher/SKILL.md +171 -0
- package/skills/content/wechat-publisher/references/api.md +105 -0
- package/skills/content/wechat-publisher/references/layout-rules.md +57 -0
- package/skills/content/wechat-publisher/references/wechat-safe-template.html +86 -0
- package/skills/content/wechat-publisher/release-check.mjs +93 -0
- package/skills/content/wechat-publisher/scripts/md_to_wechat_html.py +194 -0
- package/skills/content/wechat-publisher/scripts/publish.py +239 -0
- package/skills/content/wechat-search/LICENSE +3 -0
- package/skills/content/wechat-search/SKILL.md +211 -0
- package/skills/content/wechat-search/release-check.mjs +93 -0
- package/skills/content/wechat-search/scripts/start-chrome.sh +83 -0
- package/skills/content/xai-search/LICENSE +3 -0
- package/skills/content/xai-search/SKILL.md +79 -0
- package/skills/content/xai-search/release-check.mjs +93 -0
- package/skills/content/xai-search/scripts/xai_search.sh +187 -0
- package/skills/content/xai-search/tests/smoke_test.sh +36 -0
- package/skills/core/distill-writing/LICENSE +3 -0
- package/skills/core/distill-writing/SKILL.md +74 -0
- package/skills/core/distill-writing/references/extraction.md +95 -0
- package/skills/core/distill-writing/references/updating.md +46 -0
- package/skills/core/distill-writing/release-check.mjs +93 -0
- package/skills/core/doc-to-md/LICENSE +3 -0
- package/skills/core/doc-to-md/SKILL.md +78 -0
- package/skills/core/doc-to-md/release-check.mjs +93 -0
- package/skills/core/doc-to-md/scripts/convert.py +157 -0
- package/skills/core/editorial-review/LICENSE +3 -0
- package/skills/core/editorial-review/SKILL.md +79 -0
- package/skills/core/editorial-review/references/checklist.md +94 -0
- package/skills/core/editorial-review/release-check.mjs +93 -0
- package/skills/core/house-style/LICENSE +3 -0
- package/skills/core/house-style/SKILL.md +33 -0
- package/skills/core/house-style/references/defaults.md +66 -0
- package/skills/core/house-style/references/rules.md +267 -0
- package/skills/core/house-style/references/sources.md +27 -0
- package/skills/core/house-style/references/style-en.md +131 -0
- package/skills/core/house-style/references/style-zh.md +141 -0
- package/skills/core/house-style/references/terminology-zh.md +223 -0
- package/skills/core/house-style/release-check.mjs +93 -0
- package/skills/core/house-style/templates/brd.md +103 -0
- package/skills/core/house-style/templates/commercial-proposal.md +93 -0
- package/skills/core/house-style/templates/compliance-policy.md +109 -0
- package/skills/core/house-style/templates/gap-analysis.md +105 -0
- package/skills/core/house-style/templates/general.md +63 -0
- package/skills/core/house-style/templates/integration-guide.md +98 -0
- package/skills/core/house-style/templates/prd.md +81 -0
- package/skills/core/house-style/templates/risk-operations-procedure.md +94 -0
- package/skills/core/house-style/templates/technical-spec.md +96 -0
- package/skills/core/polish-cn/LICENSE +3 -0
- package/skills/core/polish-cn/SKILL.md +102 -0
- package/skills/core/polish-cn/references/brief.md +93 -0
- package/skills/core/polish-cn/references/models.md +76 -0
- package/skills/core/polish-cn/release-check.mjs +93 -0
- package/skills/core/polish-cn/scripts/polish-cn.test.mjs +244 -0
- package/skills/core/polish-cn/scripts/polish_blocks.py +489 -0
- package/skills/core/reg-parser/LICENSE +3 -0
- package/skills/core/reg-parser/SKILL.md +212 -0
- package/skills/core/reg-parser/references/checklist-schema.md +223 -0
- package/skills/core/reg-parser/references/checklists/hk-amlo-checklist.json +1306 -0
- package/skills/core/reg-parser/references/checklists/hk-amlo-checklist.md +469 -0
- package/skills/core/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.json +634 -0
- package/skills/core/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.md +233 -0
- package/skills/core/reg-parser/references/checklists/hk-mso-guideline-checklist.json +2194 -0
- package/skills/core/reg-parser/references/checklists/hk-mso-guideline-checklist.md +771 -0
- package/skills/core/reg-parser/references/checklists/kyc-aml-checklist.md +258 -0
- package/skills/core/reg-parser/references/checklists/visa-vars-checklist.md +1058 -0
- package/skills/core/reg-parser/references/mandates/hk-amlo-cap615.md +389 -0
- package/skills/core/reg-parser/references/mandates/visa-vars.md +205 -0
- package/skills/core/reg-parser/release-check.mjs +93 -0
- package/skills/core/reg-parser/scripts/compare_checklist.py +230 -0
- package/skills/core/reg-parser/scripts/dump_checklist.py +361 -0
- package/skills/core/reg-parser/scripts/preprocess-mandate.sh +187 -0
- package/skills/core/reg-parser/scripts/reg-parser.test.mjs +165 -0
- package/skills/core/reg-parser/scripts/test_quarantine.sh +105 -0
- package/skills/core/reg-parser/scripts/validate_checklist.py +563 -0
- package/skills/core/reg-parser/scripts/validate_mandate.py +273 -0
- package/skills/core/terminology/LICENSE +3 -0
- package/skills/core/terminology/SKILL.md +62 -0
- package/skills/core/terminology/references/format.md +50 -0
- package/skills/core/terminology/references/init.md +32 -0
- package/skills/core/terminology/release-check.mjs +93 -0
- package/skills/core/write-doc/LICENSE +3 -0
- package/skills/core/write-doc/SKILL.md +141 -0
- package/skills/core/write-doc/references/bilingual.md +60 -0
- package/skills/core/write-doc/release-check.mjs +93 -0
- package/skills/engineering/better-review/LICENSE +3 -0
- package/skills/engineering/better-review/SKILL.md +249 -0
- package/skills/engineering/better-review/agents/openai.yaml +9 -0
- package/skills/engineering/better-review/references/domain-hazards.md +53 -0
- package/skills/engineering/better-review/references/passes.md +147 -0
- package/skills/engineering/better-review/references/result.md +151 -0
- package/skills/engineering/better-review/release-check.mjs +93 -0
- package/skills/engineering/better-review/scripts/pr-context.mjs +212 -0
- package/skills/engineering/better-review/scripts/pr-context.test.mjs +168 -0
- package/skills/engineering/better-review/scripts/rereview-scope.mjs +503 -0
- package/skills/engineering/better-review/scripts/rereview-scope.test.mjs +587 -0
- package/skills/engineering/better-review/scripts/scan-diff.mjs +365 -0
- package/skills/engineering/better-review/scripts/scan-diff.test.mjs +414 -0
- package/skills/engineering/better-review/scripts/vendor-sync.test.mjs +96 -0
- package/skills/engineering/e2e-test/LICENSE +3 -0
- package/skills/engineering/e2e-test/SKILL.md +98 -0
- package/skills/engineering/e2e-test/assets/ci-gates.cloudbuild.yaml +24 -0
- package/skills/engineering/e2e-test/references/authoring/auth-flows.md +159 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-config.md +73 -0
- package/skills/engineering/e2e-test/references/authoring/playwright-patterns.md +144 -0
- package/skills/engineering/e2e-test/references/ci-integration.md +25 -0
- package/skills/engineering/e2e-test/references/ci-playwright-container.md +290 -0
- package/skills/engineering/e2e-test/references/presentation-sweep.md +104 -0
- package/skills/engineering/e2e-test/references/reviewing.md +41 -0
- package/skills/engineering/e2e-test/references/route-manifest.md +51 -0
- package/skills/engineering/e2e-test/release-check.mjs +93 -0
- package/skills/engineering/e2e-test/scripts/detect-routes-nextjs.mjs +200 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.mjs +171 -0
- package/skills/engineering/e2e-test/scripts/presentation-checks.test.mjs +106 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.mjs +179 -0
- package/skills/engineering/e2e-test/scripts/presentation-perceivability.test.mjs +117 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.mjs +154 -0
- package/skills/engineering/e2e-test/scripts/presentation-reachability.test.mjs +69 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.mjs +141 -0
- package/skills/engineering/e2e-test/scripts/presentation-render-health.test.mjs +98 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.mjs +147 -0
- package/skills/engineering/e2e-test/scripts/presentation-sweep.test.mjs +71 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.mjs +127 -0
- package/skills/engineering/e2e-test/scripts/presentation-temporal.test.mjs +59 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.mjs +82 -0
- package/skills/engineering/e2e-test/scripts/project-route-manifest.test.mjs +76 -0
- package/skills/engineering/e2e-test/scripts/validate-manifest.mjs +106 -0
- package/skills/engineering/engineering-runtime/LICENSE +3 -0
- package/skills/engineering/engineering-runtime/SKILL.md +11 -0
- package/skills/engineering/engineering-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/engineering-runtime/coherence/workflow.json +597 -0
- package/skills/engineering/engineering-runtime/engineering-runtime.test.mjs +68 -0
- package/skills/engineering/engineering-runtime/release-check.mjs +93 -0
- package/skills/engineering/engineering-runtime/scripts/exact-head-artifact.mjs +131 -0
- package/skills/engineering/engineering-runtime/scripts/head-check-set.mjs +398 -0
- package/skills/engineering/engineering-runtime/scripts/invocation-policy.mjs +187 -0
- package/skills/engineering/engineering-runtime/scripts/invocation-policy.test.mjs +95 -0
- package/skills/engineering/engineering-runtime/scripts/main-module.mjs +79 -0
- package/skills/engineering/engineering-runtime/scripts/main-module.test.mjs +288 -0
- package/skills/engineering/engineering-runtime/scripts/mergify-yaml.mjs +11 -0
- package/skills/engineering/engineering-runtime/scripts/package-lock.json +43 -0
- package/skills/engineering/engineering-runtime/scripts/package.json +10 -0
- package/skills/engineering/engineering-runtime/scripts/required-check-plan.mjs +223 -0
- package/skills/engineering/engineering-runtime/scripts/required-check-plan.test.mjs +96 -0
- package/skills/engineering/engineering-runtime/scripts/review-completion.mjs +56 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +595 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +189 -0
- package/skills/engineering/engineering-runtime/scripts/yaml-mapping.mjs +18 -0
- package/skills/engineering/ensure-coverage/LICENSE +3 -0
- package/skills/engineering/ensure-coverage/SKILL.md +129 -0
- package/skills/engineering/ensure-coverage/references/breadth/coverage-ledger.md +92 -0
- package/skills/engineering/ensure-coverage/references/breadth/inventory-contract.md +85 -0
- package/skills/engineering/ensure-coverage/references/breadth/surface-baseline.md +44 -0
- package/skills/engineering/ensure-coverage/references/breadth/surface-discovery.md +16 -0
- package/skills/engineering/ensure-coverage/references/depth/characterization.md +68 -0
- package/skills/engineering/ensure-coverage/references/depth/coverage.config.example.json +19 -0
- package/skills/engineering/ensure-coverage/references/depth/grading.md +35 -0
- package/skills/engineering/ensure-coverage/references/depth/mock-policy.md +57 -0
- package/skills/engineering/ensure-coverage/references/depth/test-smells.md +39 -0
- package/skills/engineering/ensure-coverage/references/enforcement/ci-contract.md +44 -0
- package/skills/engineering/ensure-coverage/references/examples/coverage-ledger.md +110 -0
- package/skills/engineering/ensure-coverage/references/examples/refund-flow.md +35 -0
- package/skills/engineering/ensure-coverage/references/presentation/axis.md +64 -0
- package/skills/engineering/ensure-coverage/references/process/audit-mode.md +27 -0
- package/skills/engineering/ensure-coverage/references/process/output-template.md +139 -0
- package/skills/engineering/ensure-coverage/references/process/test-strategy.md +56 -0
- package/skills/engineering/ensure-coverage/release-check.mjs +93 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-config.schema.json +67 -0
- package/skills/engineering/ensure-coverage/schemas/coverage-file.schema.json +140 -0
- package/skills/engineering/ensure-coverage/scripts/README.md +99 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.mjs +182 -0
- package/skills/engineering/ensure-coverage/scripts/adapters/nextjs-inventory.test.mjs +96 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.mjs +105 -0
- package/skills/engineering/ensure-coverage/scripts/check-quarantine-expiry.test.mjs +47 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.mjs +137 -0
- package/skills/engineering/ensure-coverage/scripts/ci-audit.test.mjs +86 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.mjs +674 -0
- package/skills/engineering/ensure-coverage/scripts/coverage-ledger.test.mjs +447 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.mjs +591 -0
- package/skills/engineering/ensure-coverage/scripts/design-parity.test.mjs +552 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.mjs +282 -0
- package/skills/engineering/ensure-coverage/scripts/lint-tests.test.mjs +289 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/ensure-coverage/scripts/mock-policy-config.test.mjs +119 -0
- package/skills/engineering/ensure-coverage/scripts/package.json +19 -0
- package/skills/engineering/golden-path/LICENSE +3 -0
- package/skills/engineering/golden-path/SKILL.md +230 -0
- package/skills/engineering/golden-path/agents/openai.yaml +3 -0
- package/skills/engineering/golden-path/assets/golden-paths.example.json +57 -0
- package/skills/engineering/golden-path/references/contract.md +239 -0
- package/skills/engineering/golden-path/references/migration.md +111 -0
- package/skills/engineering/golden-path/release-check.mjs +93 -0
- package/skills/engineering/golden-path/scripts/golden-path-core.mjs +1779 -0
- package/skills/engineering/golden-path/scripts/golden-path.mjs +6 -0
- package/skills/engineering/golden-path/scripts/golden-path.test.mjs +1457 -0
- package/skills/engineering/harness-runtime/LICENSE +3 -0
- package/skills/engineering/harness-runtime/SKILL.md +19 -0
- package/skills/engineering/harness-runtime/agents/openai.yaml +6 -0
- package/skills/engineering/harness-runtime/bin/discover-models.mjs +4 -0
- package/skills/engineering/harness-runtime/bin/model-catalog.mjs +4 -0
- package/skills/engineering/harness-runtime/contracts.md +15 -0
- package/skills/engineering/harness-runtime/discover-models.mjs +392 -0
- package/skills/engineering/harness-runtime/discover-models.test.mjs +363 -0
- package/skills/engineering/harness-runtime/fixtures/native-question-schemas.json +33 -0
- package/skills/engineering/harness-runtime/fixtures/question-responses.json +54 -0
- package/skills/engineering/harness-runtime/harness-runtime.test.mjs +967 -0
- package/skills/engineering/harness-runtime/index.mjs +767 -0
- package/skills/engineering/harness-runtime/model-catalog-seed.test.mjs +829 -0
- package/skills/engineering/harness-runtime/model-catalog.mjs +787 -0
- package/skills/engineering/harness-runtime/model-catalog.test.mjs +366 -0
- package/skills/engineering/harness-runtime/native-question-contracts.md +37 -0
- package/skills/engineering/harness-runtime/references/model-catalog-seed.json +408 -0
- package/skills/engineering/harness-runtime/references/model-catalog.md +57 -0
- package/skills/engineering/harness-runtime/release-check.mjs +93 -0
- package/skills/engineering/resolve-issues/LICENSE +3 -0
- package/skills/engineering/resolve-issues/SKILL.md +250 -0
- package/skills/engineering/resolve-issues/agents/openai.yaml +9 -0
- package/skills/engineering/resolve-issues/plugin-hooks.json +17 -0
- package/skills/engineering/resolve-issues/references/canary.md +28 -0
- package/skills/engineering/resolve-issues/references/ci.md +105 -0
- package/skills/engineering/resolve-issues/references/done.md +25 -0
- package/skills/engineering/resolve-issues/references/dropbox.md +90 -0
- package/skills/engineering/resolve-issues/references/expire.md +318 -0
- package/skills/engineering/resolve-issues/references/exploration.md +202 -0
- package/skills/engineering/resolve-issues/references/implementation.md +303 -0
- package/skills/engineering/resolve-issues/references/preflight.md +445 -0
- package/skills/engineering/resolve-issues/references/review.md +228 -0
- package/skills/engineering/resolve-issues/references/shared-modules.md +44 -0
- package/skills/engineering/resolve-issues/references/task-plan.md +264 -0
- package/skills/engineering/resolve-issues/release-check.mjs +93 -0
- package/skills/engineering/resolve-issues/scripts/cleanup-runs.mjs +364 -0
- package/skills/engineering/resolve-issues/scripts/cleanup-runs.test.mjs +280 -0
- package/skills/engineering/resolve-issues/scripts/discover-models.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/dropbox.mjs +473 -0
- package/skills/engineering/resolve-issues/scripts/dropbox.test.mjs +346 -0
- package/skills/engineering/resolve-issues/scripts/findings-reuse.mjs +98 -0
- package/skills/engineering/resolve-issues/scripts/findings-reuse.test.mjs +88 -0
- package/skills/engineering/resolve-issues/scripts/github-reviews.mjs +384 -0
- package/skills/engineering/resolve-issues/scripts/github-reviews.test.mjs +264 -0
- package/skills/engineering/resolve-issues/scripts/install-hooks.mjs +135 -0
- package/skills/engineering/resolve-issues/scripts/install-hooks.test.mjs +79 -0
- package/skills/engineering/resolve-issues/scripts/issue-tree.mjs +162 -0
- package/skills/engineering/resolve-issues/scripts/issue-tree.test.mjs +107 -0
- package/skills/engineering/resolve-issues/scripts/manual-invocation.test.mjs +14 -0
- package/skills/engineering/resolve-issues/scripts/model-catalog.mjs +9 -0
- package/skills/engineering/resolve-issues/scripts/next-actions-capacity.test.mjs +149 -0
- package/skills/engineering/resolve-issues/scripts/next-actions.mjs +856 -0
- package/skills/engineering/resolve-issues/scripts/next-actions.test.mjs +915 -0
- package/skills/engineering/resolve-issues/scripts/plan-sync.mjs +269 -0
- package/skills/engineering/resolve-issues/scripts/plan-sync.test.mjs +156 -0
- package/skills/engineering/resolve-issues/scripts/preflight-models.mjs +736 -0
- package/skills/engineering/resolve-issues/scripts/preflight-models.test.mjs +448 -0
- package/skills/engineering/resolve-issues/scripts/ready-check.mjs +185 -0
- package/skills/engineering/resolve-issues/scripts/ready-check.test.mjs +217 -0
- package/skills/engineering/resolve-issues/scripts/rehydrate.mjs +98 -0
- package/skills/engineering/resolve-issues/scripts/rehydrate.test.mjs +91 -0
- package/skills/engineering/resolve-issues/scripts/review-verdict.mjs +509 -0
- package/skills/engineering/resolve-issues/scripts/review-verdict.test.mjs +1060 -0
- package/skills/engineering/resolve-issues/scripts/size-check.mjs +492 -0
- package/skills/engineering/resolve-issues/scripts/size-check.test.mjs +458 -0
- package/skills/engineering/resolve-release/LICENSE +3 -0
- package/skills/engineering/resolve-release/SKILL.md +215 -0
- package/skills/engineering/resolve-release/agents/openai.yaml +8 -0
- package/skills/engineering/resolve-release/flows/cloud-run-canary.md +13 -0
- package/skills/engineering/resolve-release/flows/cloud-run.md +7 -0
- package/skills/engineering/resolve-release/flows/root-tag-npm.md +13 -0
- package/skills/engineering/resolve-release/flows/workspace-npm.md +22 -0
- package/skills/engineering/resolve-release/references/canary.md +51 -0
- package/skills/engineering/resolve-release/references/candidate.md +41 -0
- package/skills/engineering/resolve-release/references/cut.md +131 -0
- package/skills/engineering/resolve-release/references/dark-launch.md +66 -0
- package/skills/engineering/resolve-release/references/flows.md +150 -0
- package/skills/engineering/resolve-release/references/preflight.md +154 -0
- package/skills/engineering/resolve-release/references/prepared-metadata.md +260 -0
- package/skills/engineering/resolve-release/references/promotion.md +82 -0
- package/skills/engineering/resolve-release/references/publish.md +232 -0
- package/skills/engineering/resolve-release/references/workspace-npm.md +103 -0
- package/skills/engineering/resolve-release/release-check.mjs +93 -0
- package/skills/engineering/resolve-release/scripts/apply.mjs +212 -0
- package/skills/engineering/resolve-release/scripts/apply.test.mjs +99 -0
- package/skills/engineering/resolve-release/scripts/dark-flags.mjs +134 -0
- package/skills/engineering/resolve-release/scripts/dark-flags.test.mjs +100 -0
- package/skills/engineering/resolve-release/scripts/flow.mjs +500 -0
- package/skills/engineering/resolve-release/scripts/flow.test.mjs +340 -0
- package/skills/engineering/resolve-release/scripts/green-head.mjs +231 -0
- package/skills/engineering/resolve-release/scripts/green-head.test.mjs +101 -0
- package/skills/engineering/resolve-release/scripts/npm-version-absence.mjs +138 -0
- package/skills/engineering/resolve-release/scripts/npm-version-absence.test.mjs +426 -0
- package/skills/engineering/resolve-release/scripts/plan-npm.test.mjs +659 -0
- package/skills/engineering/resolve-release/scripts/plan-toml-boundary.test.mjs +317 -0
- package/skills/engineering/resolve-release/scripts/plan-uv.test.mjs +291 -0
- package/skills/engineering/resolve-release/scripts/plan.mjs +806 -0
- package/skills/engineering/resolve-release/scripts/plan.test.mjs +428 -0
- package/skills/engineering/rush-issues/LICENSE +3 -0
- package/skills/engineering/rush-issues/SKILL.md +58 -0
- package/skills/engineering/rush-issues/agents/openai.yaml +8 -0
- package/skills/engineering/rush-issues/rehydrate.mjs +10 -0
- package/skills/engineering/rush-issues/release-check.mjs +93 -0
- package/skills/engineering/rush-release/LICENSE +3 -0
- package/skills/engineering/rush-release/SKILL.md +35 -0
- package/skills/engineering/rush-release/agents/openai.yaml +8 -0
- package/skills/engineering/rush-release/release-check.mjs +93 -0
- package/skills/engineering/test-quality/LICENSE +3 -0
- package/skills/engineering/test-quality/SKILL.md +79 -0
- package/skills/engineering/test-quality/references/audit.md +80 -0
- package/skills/engineering/test-quality/references/lint.md +24 -0
- package/skills/engineering/test-quality/references/principles.md +143 -0
- package/skills/engineering/test-quality/references/testing-conventions.md +9 -0
- package/skills/engineering/test-quality/release-check.mjs +93 -0
- package/skills/engineering/test-quality/scripts/lint-tests.mjs +574 -0
- package/skills/engineering/test-quality/scripts/lint-tests.test.mjs +591 -0
- package/skills/engineering/test-quality/scripts/mock-policy-config.mjs +176 -0
- package/skills/engineering/test-quality/scripts/mock-policy-config.test.mjs +119 -0
- package/skills/engineering/test-quality/scripts/persist-conventions-core.mjs +117 -0
- package/skills/engineering/test-quality/scripts/persist-conventions.mjs +17 -0
- package/skills/engineering/test-quality/scripts/persist-conventions.test.mjs +104 -0
- package/skills/risk-compliance/compliance-audit/LICENSE +3 -0
- package/skills/risk-compliance/compliance-audit/SKILL.md +439 -0
- package/skills/risk-compliance/compliance-audit/references/findings-schema.md +293 -0
- package/skills/risk-compliance/compliance-audit/references/normalization-rules.md +45 -0
- package/skills/risk-compliance/compliance-audit/references/vars-checklist.md +1068 -0
- package/skills/risk-compliance/compliance-audit/references/vars-findings-schema.md +398 -0
- package/skills/risk-compliance/compliance-audit/release-check.mjs +93 -0
- package/skills/risk-compliance/compliance-audit/scripts/compliance-audit.test.mjs +14 -0
- package/skills/risk-compliance/compliance-audit/scripts/export_tracker_xlsx.py +221 -0
- package/skills/risk-compliance/compliance-audit/scripts/reconcile_tracker.py +458 -0
- package/skills/risk-compliance/compliance-audit/scripts/test_export_tracker_xlsx.py +97 -0
- package/skills/risk-compliance/compliance-audit/scripts/test_validate_tracker.py +157 -0
- package/skills/risk-compliance/compliance-audit/scripts/validate_tracker.py +829 -0
- package/skills/risk-compliance/contract-compare/LICENSE +3 -0
- package/skills/risk-compliance/contract-compare/SKILL.md +199 -0
- package/skills/risk-compliance/contract-compare/references/comparison-dimensions.md +209 -0
- package/skills/risk-compliance/contract-compare/release-check.mjs +93 -0
- package/skills/risk-compliance/contract-review/LICENSE +3 -0
- package/skills/risk-compliance/contract-review/SKILL.md +240 -0
- package/skills/risk-compliance/contract-review/references/review-criteria.md +223 -0
- package/skills/risk-compliance/contract-review/release-check.mjs +93 -0
- package/skills/risk-compliance/doc-authenticity/LICENSE +3 -0
- package/skills/risk-compliance/doc-authenticity/SKILL.md +160 -0
- package/skills/risk-compliance/doc-authenticity/agents/openai.yaml +8 -0
- package/skills/risk-compliance/doc-authenticity/manual-invocation.test.mjs +12 -0
- package/skills/risk-compliance/doc-authenticity/references/agreement.md +66 -0
- package/skills/risk-compliance/doc-authenticity/references/bank-statement.md +150 -0
- package/skills/risk-compliance/doc-authenticity/references/forensic-signals.md +157 -0
- package/skills/risk-compliance/doc-authenticity/references/image-signals.md +114 -0
- package/skills/risk-compliance/doc-authenticity/references/invoice.md +66 -0
- package/skills/risk-compliance/doc-authenticity/references/issuer-profiles.md +86 -0
- package/skills/risk-compliance/doc-authenticity/references/verdict-and-report.md +95 -0
- package/skills/risk-compliance/doc-authenticity/references/verdict.schema.json +81 -0
- package/skills/risk-compliance/doc-authenticity/release-check.mjs +93 -0
- package/skills/risk-compliance/doc-authenticity/scripts/image_forensics.py +294 -0
- package/skills/risk-compliance/doc-authenticity/scripts/pdf_forensics.py +401 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_codes.py +224 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.py +308 -0
- package/skills/risk-compliance/doc-authenticity/scripts/validate_verdict.test.mjs +212 -0
- package/skills/risk-compliance/fraud-analysis/LICENSE +3 -0
- package/skills/risk-compliance/fraud-analysis/SKILL.md +114 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/authorized-payment-scam.md +41 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/first-party-fraud.md +44 -0
- package/skills/risk-compliance/fraud-analysis/references/archetypes/third-party-fraud.md +27 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/bank-transfer.md +24 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/card-payment.md +30 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/payment-collection.md +20 -0
- package/skills/risk-compliance/fraud-analysis/references/contexts/payout.md +20 -0
- package/skills/risk-compliance/fraud-analysis/references/feature-engineering.md +158 -0
- package/skills/risk-compliance/fraud-analysis/references/mechanisms/account-takeover.md +36 -0
- package/skills/risk-compliance/fraud-analysis/references/report-rationale.md +45 -0
- package/skills/risk-compliance/fraud-analysis/references/report-template.md +190 -0
- package/skills/risk-compliance/fraud-analysis/references/review-checklist.md +175 -0
- package/skills/risk-compliance/fraud-analysis/references/taxonomy.md +79 -0
- package/skills/risk-compliance/fraud-analysis/references/terminology.md +108 -0
- package/skills/risk-compliance/fraud-analysis/references/workflow.md +175 -0
- package/skills/risk-compliance/fraud-analysis/release-check.mjs +93 -0
- package/skills/risk-compliance/payment-analysis/LICENSE +3 -0
- package/skills/risk-compliance/payment-analysis/SKILL.md +180 -0
- package/skills/risk-compliance/payment-analysis/references/auth-rate-actions.md +30 -0
- package/skills/risk-compliance/payment-analysis/references/chargebacks.md +208 -0
- package/skills/risk-compliance/payment-analysis/references/chinese-polish.md +51 -0
- package/skills/risk-compliance/payment-analysis/references/event-layers.md +127 -0
- package/skills/risk-compliance/payment-analysis/references/fx.md +59 -0
- package/skills/risk-compliance/payment-analysis/references/journey.md +79 -0
- package/skills/risk-compliance/payment-analysis/references/metrics.md +67 -0
- package/skills/risk-compliance/payment-analysis/references/report-template.md +119 -0
- package/skills/risk-compliance/payment-analysis/references/terminology.md +95 -0
- package/skills/risk-compliance/payment-analysis/references/visualization.md +56 -0
- package/skills/risk-compliance/payment-analysis/release-check.mjs +93 -0
- package/skills/risk-compliance/report-writing/LICENSE +3 -0
- package/skills/risk-compliance/report-writing/SKILL.md +220 -0
- package/skills/risk-compliance/report-writing/references/audit-report-template.md +121 -0
- package/skills/risk-compliance/report-writing/references/external-assessment-template.md +167 -0
- package/skills/risk-compliance/report-writing/references/management-report-template.md +145 -0
- package/skills/risk-compliance/report-writing/references/vars-report-template.md +224 -0
- package/skills/risk-compliance/report-writing/release-check.mjs +93 -0
- package/skills/risk-compliance/similar-domain/LICENSE +3 -0
- package/skills/risk-compliance/similar-domain/SKILL.md +203 -0
- package/skills/risk-compliance/similar-domain/references/entities.md +67 -0
- package/skills/risk-compliance/similar-domain/references/fingerprints.md +134 -0
- package/skills/risk-compliance/similar-domain/references/pivots.md +82 -0
- package/skills/risk-compliance/similar-domain/references/report-template.md +93 -0
- package/skills/risk-compliance/similar-domain/references/scoring.md +130 -0
- package/skills/risk-compliance/similar-domain/references/terminology.md +41 -0
- package/skills/risk-compliance/similar-domain/references/workflow.md +85 -0
- package/skills/risk-compliance/similar-domain/release-check.mjs +93 -0
- package/skills/risk-compliance/tld-detection/LICENSE +3 -0
- package/skills/risk-compliance/tld-detection/SKILL.md +245 -0
- package/skills/risk-compliance/tld-detection/agents/openai.yaml +9 -0
- package/skills/risk-compliance/tld-detection/references/chinese-polish.md +55 -0
- package/skills/risk-compliance/tld-detection/references/clean.md +51 -0
- package/skills/risk-compliance/tld-detection/references/clustering.md +235 -0
- package/skills/risk-compliance/tld-detection/references/decision.md +189 -0
- package/skills/risk-compliance/tld-detection/references/fx-conversion.md +232 -0
- package/skills/risk-compliance/tld-detection/references/report-template.md +272 -0
- package/skills/risk-compliance/tld-detection/references/streams.md +141 -0
- package/skills/risk-compliance/tld-detection/references/terminology.md +95 -0
- package/skills/risk-compliance/tld-detection/references/workflow.md +95 -0
- package/skills/risk-compliance/tld-detection/release-check.mjs +93 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_ladders.py +390 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_ladders.test.mjs +14 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_streams.py +650 -0
- package/skills/risk-compliance/tld-detection/scripts/detect_streams.test.mjs +14 -0
- package/skills/risk-compliance/tld-detection/tests/test_detect_ladders.py +134 -0
- package/skills/risk-compliance/tld-detection/tests/test_detect_streams.py +520 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs-fullstack
|
|
3
|
+
description: "Build or debug Next.js App Router features with React 19 — pages/layouts/route handlers, Server/Client Components, Server Actions, forms, middleware, DAL, strict TypeScript, Zod — plus our conventions: nuqs URL state, SWR cache, Skeleton/Progress + Sonner feedback, drag-and-drop upload, the portal app shell, list pages as filter/sort/paginate tables. shadcn component mechanics: see the shadcn skill."
|
|
4
|
+
release-version: 0.36.0
|
|
5
|
+
---
|
|
6
|
+
**Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
|
|
7
|
+
# Next.js 16 Fullstack Development
|
|
8
|
+
|
|
9
|
+
**Stack:** Next.js 16 (App Router) | React 19 | TypeScript strict | Zod | Prisma
|
|
10
|
+
|
|
11
|
+
## Quick Reference
|
|
12
|
+
|
|
13
|
+
- [Architectural Conventions](conventions.md) - Layers, DAL, testing
|
|
14
|
+
- [Next.js 16 Patterns](nextjs16.md) - App Router, components, routing
|
|
15
|
+
- [Server Actions & Forms](server-actions.md) - useActionState, withCallbacks
|
|
16
|
+
- [Frontend Conventions](frontend-conventions.md) - nuqs URL state, SWR cache, feedback (Progress/Sonner), file upload, portal app shell, i18n, list pages (components → `shadcn`)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Core Principles
|
|
21
|
+
|
|
22
|
+
1. **Server Components by default** - Client Components only when needed
|
|
23
|
+
2. **Server Actions for mutations** - Not API routes for forms
|
|
24
|
+
3. **DAL for database access** - Never call Prisma from components
|
|
25
|
+
4. **Zod for validation** - At server action boundary
|
|
26
|
+
5. **TypeScript strict mode** - Explicit return types on exports
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Project Structure
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
src/
|
|
34
|
+
├── app/
|
|
35
|
+
│ ├── layout.tsx
|
|
36
|
+
│ ├── page.tsx
|
|
37
|
+
│ ├── (public)/... # Public routes
|
|
38
|
+
│ ├── dashboard/
|
|
39
|
+
│ │ ├── layout.tsx
|
|
40
|
+
│ │ ├── page.tsx
|
|
41
|
+
│ │ ├── settings/
|
|
42
|
+
│ │ │ ├── page.tsx
|
|
43
|
+
│ │ │ ├── actions.ts # Route-scoped server actions
|
|
44
|
+
│ │ │ ├── schema.ts # Route-scoped validation
|
|
45
|
+
│ │ │ └── components/
|
|
46
|
+
│ │ └── [id]/
|
|
47
|
+
│ │ └── page.tsx
|
|
48
|
+
│ └── api/
|
|
49
|
+
│ └── health/
|
|
50
|
+
│ └── route.ts
|
|
51
|
+
├── lib/
|
|
52
|
+
│ ├── auth.ts # Auth configuration
|
|
53
|
+
│ ├── prisma.ts # Database client
|
|
54
|
+
│ └── server-action.ts # Action utilities
|
|
55
|
+
├── dal/
|
|
56
|
+
│ └── user.ts # Data access layer
|
|
57
|
+
├── components/
|
|
58
|
+
│ ├── ui/ # Shared primitives
|
|
59
|
+
│ └── client/ # Reusable client components
|
|
60
|
+
└── context/
|
|
61
|
+
└── session-context.tsx
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Architectural Layers
|
|
67
|
+
|
|
68
|
+
### 1. UI Layer (Components & Pages)
|
|
69
|
+
|
|
70
|
+
- Location: `app/**`, `components/**`
|
|
71
|
+
- Renders UI (RSC or client components)
|
|
72
|
+
- Calls server actions (via import or `useActionState`)
|
|
73
|
+
- No direct Prisma usage
|
|
74
|
+
|
|
75
|
+
### 2. Use Case Layer (Server Actions)
|
|
76
|
+
|
|
77
|
+
- Location: `app/**/actions.ts`
|
|
78
|
+
- Always begins with `'use server'`
|
|
79
|
+
- Validates input with Zod
|
|
80
|
+
- Enforces auth and permissions
|
|
81
|
+
- Calls DAL for database operations
|
|
82
|
+
- Returns typed `ActionResult` shape
|
|
83
|
+
|
|
84
|
+
### 3. Data Access Layer (DAL)
|
|
85
|
+
|
|
86
|
+
- Location: `lib/repositories/**` or `dal/**`
|
|
87
|
+
- All Prisma access
|
|
88
|
+
- Framework-agnostic (no Next.js, no auth)
|
|
89
|
+
- Returns domain objects or `null`
|
|
90
|
+
- No Zod schemas, no logging
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Server Action Pattern
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
// app/dashboard/settings/actions.ts
|
|
98
|
+
'use server';
|
|
99
|
+
|
|
100
|
+
import { z } from 'zod';
|
|
101
|
+
import { revalidatePath } from 'next/cache';
|
|
102
|
+
import { auth } from '@/lib/auth';
|
|
103
|
+
import { updateUserProfile } from '@/dal/user';
|
|
104
|
+
|
|
105
|
+
const schema = z.object({
|
|
106
|
+
name: z.string().min(1).max(50),
|
|
107
|
+
avatarUrl: z.string().url().optional(),
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
export type ActionResult<T = unknown> = {
|
|
111
|
+
success: boolean;
|
|
112
|
+
data?: T;
|
|
113
|
+
error?: { code: string; message: string };
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
export async function updateProfile(input: unknown): Promise<ActionResult> {
|
|
117
|
+
const session = await auth();
|
|
118
|
+
if (!session?.user) {
|
|
119
|
+
return { success: false, error: { code: 'UNAUTHENTICATED', message: 'Please sign in.' } };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const parsed = schema.safeParse(input);
|
|
123
|
+
if (!parsed.success) {
|
|
124
|
+
return { success: false, error: { code: 'VALIDATION_ERROR', message: 'Invalid input.' } };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
const user = await updateUserProfile(session.user.id, parsed.data);
|
|
129
|
+
revalidatePath('/dashboard/settings');
|
|
130
|
+
return { success: true, data: user };
|
|
131
|
+
} catch (err) {
|
|
132
|
+
console.error(err);
|
|
133
|
+
return { success: false, error: { code: 'INTERNAL_ERROR', message: 'Something went wrong.' } };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Client Component with useActionState
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
'use client';
|
|
144
|
+
|
|
145
|
+
import { startTransition, useActionState } from 'react';
|
|
146
|
+
import { useForm } from 'react-hook-form';
|
|
147
|
+
import { zodResolver } from '@hookform/resolvers/zod';
|
|
148
|
+
import { toast } from 'sonner';
|
|
149
|
+
import { updateProfile } from './actions';
|
|
150
|
+
|
|
151
|
+
export function ProfileForm() {
|
|
152
|
+
const { register, handleSubmit } = useForm({
|
|
153
|
+
resolver: zodResolver(schema),
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
const [state, formAction, isPending] = useActionState(
|
|
157
|
+
async (prev, data) => {
|
|
158
|
+
const result = await updateProfile(data);
|
|
159
|
+
if (result.success) toast.success('Profile updated');
|
|
160
|
+
else toast.error(result.error?.message);
|
|
161
|
+
return result;
|
|
162
|
+
},
|
|
163
|
+
{ success: false }
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
function onSubmit(data) {
|
|
167
|
+
startTransition(() => formAction(data));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<form onSubmit={handleSubmit(onSubmit)}>
|
|
172
|
+
<input {...register('name')} />
|
|
173
|
+
<button disabled={isPending}>Save</button>
|
|
174
|
+
</form>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Forbidden Patterns
|
|
182
|
+
|
|
183
|
+
| Pattern | Why |
|
|
184
|
+
|---------|-----|
|
|
185
|
+
| `pages/` directory | App Router only |
|
|
186
|
+
| `getServerSideProps`, `getStaticProps` | Use Server Components |
|
|
187
|
+
| `next/router` | Use `next/navigation` |
|
|
188
|
+
| Full-page client components | Bad perf |
|
|
189
|
+
| Fetching data with `useEffect` | Use Server Components |
|
|
190
|
+
| Direct Prisma in components | Use DAL |
|
|
191
|
+
| `HTTPException` from DAL | Keep DAL framework-agnostic |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Do / Don't
|
|
196
|
+
|
|
197
|
+
### Do
|
|
198
|
+
|
|
199
|
+
- Use `'use server'` actions as use-case boundaries
|
|
200
|
+
- Validate inputs with Zod before DB/auth logic
|
|
201
|
+
- Route all Prisma through repositories/DAL
|
|
202
|
+
- Return consistent `ActionResult` shapes
|
|
203
|
+
- Use explicit TS types for exports
|
|
204
|
+
|
|
205
|
+
### Don't
|
|
206
|
+
|
|
207
|
+
- Don't call Prisma from components or actions directly
|
|
208
|
+
- Don't access auth inside DAL
|
|
209
|
+
- Don't return raw errors to client
|
|
210
|
+
- Don't put business logic in DAL
|
|
211
|
+
- Don't skip input validation
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
# Architectural Conventions
|
|
2
|
+
|
|
3
|
+
## Directory & Naming
|
|
4
|
+
|
|
5
|
+
### DB Client
|
|
6
|
+
|
|
7
|
+
`lib/db/client.ts` or `lib/prisma.ts`:
|
|
8
|
+
- Export singleton Prisma client
|
|
9
|
+
- Standard safeguards for dev hot-reload
|
|
10
|
+
|
|
11
|
+
### Repositories / DAL
|
|
12
|
+
|
|
13
|
+
Location: `lib/repositories/` or `dal/`
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
lib/repositories/
|
|
17
|
+
├── userRepository.ts
|
|
18
|
+
├── orderRepository.ts
|
|
19
|
+
└── index.ts
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Naming: `<entity>Repository.ts`
|
|
23
|
+
Functions: `getUserById`, `listOrdersByUser`, `createOrder`
|
|
24
|
+
|
|
25
|
+
### Server Actions
|
|
26
|
+
|
|
27
|
+
Group by feature:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
app/(dashboard)/settings/actions.ts
|
|
31
|
+
app/(shop)/orders/[orderId]/actions.ts
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Export named actions:
|
|
35
|
+
- `export async function updateProfile(...)`
|
|
36
|
+
- `export async function createOrder(...)`
|
|
37
|
+
|
|
38
|
+
### Schemas & Types
|
|
39
|
+
|
|
40
|
+
- Shared Zod schemas: `lib/schemas/**`
|
|
41
|
+
- Domain types/DTOs: `lib/types/**`
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## TypeScript Rules
|
|
46
|
+
|
|
47
|
+
- `strict: true` in `tsconfig.json`
|
|
48
|
+
- All **exported** functions must have explicit return types
|
|
49
|
+
- Prefer **type aliases** over interfaces for simple data shapes
|
|
50
|
+
- Use `async`/`await`, avoid `.then/.catch` chaining
|
|
51
|
+
- Prefer **named exports** for repositories, actions, helpers
|
|
52
|
+
|
|
53
|
+
### Error Types
|
|
54
|
+
|
|
55
|
+
Define in `lib/errors.ts`:
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
export class NotFoundError extends Error {
|
|
59
|
+
constructor(message: string) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.name = 'NotFoundError';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export class PermissionDeniedError extends Error {
|
|
66
|
+
constructor(message: string) {
|
|
67
|
+
super(message);
|
|
68
|
+
this.name = 'PermissionDeniedError';
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Server Actions - Detailed
|
|
76
|
+
|
|
77
|
+
### File Setup
|
|
78
|
+
|
|
79
|
+
```typescript
|
|
80
|
+
'use server';
|
|
81
|
+
|
|
82
|
+
import { z } from 'zod';
|
|
83
|
+
import { auth } from '@/lib/auth';
|
|
84
|
+
import { userRepository } from '@/lib/repositories';
|
|
85
|
+
import { NotFoundError, PermissionDeniedError } from '@/lib/errors';
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Input Validation
|
|
89
|
+
|
|
90
|
+
Always use Zod:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const schema = z.object({
|
|
94
|
+
name: z.string().min(1),
|
|
95
|
+
email: z.string().email(),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
export async function updateUser(input: unknown) {
|
|
99
|
+
const parsed = schema.safeParse(input);
|
|
100
|
+
if (!parsed.success) {
|
|
101
|
+
return { success: false, error: { code: 'VALIDATION_ERROR', message: parsed.error.message } };
|
|
102
|
+
}
|
|
103
|
+
// ...
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Auth Pattern
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
const session = await auth();
|
|
111
|
+
if (!session?.user) {
|
|
112
|
+
return {
|
|
113
|
+
success: false,
|
|
114
|
+
error: { code: 'UNAUTHENTICATED', message: 'Please sign in.' },
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// For permissions
|
|
119
|
+
if (session.user.role !== 'ADMIN') {
|
|
120
|
+
return { success: false, error: { code: 'FORBIDDEN', message: 'Admins only.' } };
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Standard Response Shape
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
export type ActionError = {
|
|
128
|
+
code: string;
|
|
129
|
+
message: string;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export type ActionResult<TData = unknown> = {
|
|
133
|
+
success: boolean;
|
|
134
|
+
data?: TData;
|
|
135
|
+
error?: ActionError;
|
|
136
|
+
};
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Error Mapping
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
try {
|
|
143
|
+
const data = await someRepositoryCall(...);
|
|
144
|
+
if (!data) {
|
|
145
|
+
return { success: false, error: { code: 'NOT_FOUND', message: 'Resource not found.' } };
|
|
146
|
+
}
|
|
147
|
+
return { success: true, data };
|
|
148
|
+
} catch (err) {
|
|
149
|
+
if (err instanceof PermissionDeniedError) {
|
|
150
|
+
return { success: false, error: { code: 'FORBIDDEN', message: err.message } };
|
|
151
|
+
}
|
|
152
|
+
console.error(err);
|
|
153
|
+
return { success: false, error: { code: 'INTERNAL_ERROR', message: 'Something went wrong.' } };
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Data Access Layer (Prisma)
|
|
160
|
+
|
|
161
|
+
### General Rules
|
|
162
|
+
|
|
163
|
+
- No Next.js imports (`next/headers`, etc.)
|
|
164
|
+
- No auth logic - DAL is unaware of current user
|
|
165
|
+
- No Zod schemas - inputs already validated
|
|
166
|
+
- No logging - callers decide when to log
|
|
167
|
+
|
|
168
|
+
### Repository Functions
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
// lib/repositories/userRepository.ts
|
|
172
|
+
import { db } from '../db/client';
|
|
173
|
+
import type { User } from '@prisma/client';
|
|
174
|
+
|
|
175
|
+
export async function getUserById(userId: string): Promise<User | null> {
|
|
176
|
+
return db.user.findUnique({
|
|
177
|
+
where: { id: userId },
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export async function updateUserProfile(
|
|
182
|
+
userId: string,
|
|
183
|
+
data: { name?: string | null; avatarUrl?: string | null }
|
|
184
|
+
): Promise<User> {
|
|
185
|
+
return db.user.update({
|
|
186
|
+
where: { id: userId },
|
|
187
|
+
data,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Transactions
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
export async function createOrderWithItems(args: { ... }): Promise<Order> {
|
|
196
|
+
return db.$transaction(async (tx) => {
|
|
197
|
+
const order = await tx.order.create({ ... });
|
|
198
|
+
await tx.orderItem.createMany({ ... });
|
|
199
|
+
return order;
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Handling "Not Found"
|
|
205
|
+
|
|
206
|
+
- For queries: Return `null`
|
|
207
|
+
- For update/delete: Let Prisma throw, use-case layer catches and maps to NOT_FOUND
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## Auth Integration (Better Auth)
|
|
212
|
+
|
|
213
|
+
- Use auth **only in server actions/API routes**
|
|
214
|
+
- Load session/user, enforce roles/permissions
|
|
215
|
+
- Do **not** pass auth/session objects into DAL
|
|
216
|
+
- Pass only **primitive IDs** (userId, tenantId) to repositories
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Testing Conventions
|
|
221
|
+
|
|
222
|
+
### Unit Tests (Vitest)
|
|
223
|
+
|
|
224
|
+
- Scope: Single function in isolation
|
|
225
|
+
- Location: `<filename>.test.ts` alongside source
|
|
226
|
+
- Mock all external dependencies
|
|
227
|
+
- Follow AAA: Arrange, Act, Assert
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
// lib/utils/formatCurrency.test.ts
|
|
231
|
+
import { describe, it, expect } from 'vitest';
|
|
232
|
+
import { formatCurrency } from './formatCurrency';
|
|
233
|
+
|
|
234
|
+
describe('formatCurrency', () => {
|
|
235
|
+
it('should format positive numbers', () => {
|
|
236
|
+
expect(formatCurrency(1234.56, 'USD')).toBe('$1,234.56');
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Integration Tests
|
|
242
|
+
|
|
243
|
+
- Scope: Server actions with mocked database
|
|
244
|
+
- Location: `<feature>/actions.test.ts`
|
|
245
|
+
- Test full flow: validation -> auth -> logic -> response
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
// app/(dashboard)/settings/actions.test.ts
|
|
249
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
250
|
+
import { updateProfile } from './actions';
|
|
251
|
+
import * as userDal from '@/dal/user';
|
|
252
|
+
import * as auth from '@/lib/auth';
|
|
253
|
+
|
|
254
|
+
vi.mock('@/dal/user');
|
|
255
|
+
vi.mock('@/lib/auth');
|
|
256
|
+
|
|
257
|
+
describe('updateProfile', () => {
|
|
258
|
+
it('should return UNAUTHENTICATED when no session', async () => {
|
|
259
|
+
vi.mocked(auth.auth).mockResolvedValue(null);
|
|
260
|
+
const result = await updateProfile({ name: 'Test' });
|
|
261
|
+
expect(result.success).toBe(false);
|
|
262
|
+
expect(result.error?.code).toBe('UNAUTHENTICATED');
|
|
263
|
+
});
|
|
264
|
+
});
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### E2E Tests (Playwright)
|
|
268
|
+
|
|
269
|
+
- Location: `e2e/` at project root
|
|
270
|
+
- Focus on critical user journeys
|
|
271
|
+
- Use `data-testid` attributes
|
|
272
|
+
- Use Page Object Model for selectors
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// e2e/auth.spec.ts
|
|
276
|
+
import { test, expect } from '@playwright/test';
|
|
277
|
+
|
|
278
|
+
test('should allow sign in', async ({ page }) => {
|
|
279
|
+
await page.goto('/login');
|
|
280
|
+
await page.getByTestId('email-input').fill('test@example.com');
|
|
281
|
+
await page.getByTestId('password-input').fill('password123');
|
|
282
|
+
await page.getByTestId('submit-button').click();
|
|
283
|
+
await expect(page).toHaveURL('/dashboard');
|
|
284
|
+
});
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Test Organization
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
├── lib/utils/
|
|
291
|
+
│ ├── formatCurrency.ts
|
|
292
|
+
│ └── formatCurrency.test.ts # Unit
|
|
293
|
+
├── dal/
|
|
294
|
+
│ ├── user.ts
|
|
295
|
+
│ └── user.test.ts # Integration
|
|
296
|
+
├── app/(dashboard)/settings/
|
|
297
|
+
│ ├── actions.ts
|
|
298
|
+
│ └── actions.test.ts # Integration
|
|
299
|
+
└── e2e/
|
|
300
|
+
├── auth.spec.ts # E2E
|
|
301
|
+
└── fixtures/
|
|
302
|
+
└── auth.ts
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Testing Do / Don't
|
|
306
|
+
|
|
307
|
+
**Do:**
|
|
308
|
+
- Write unit tests for utilities
|
|
309
|
+
- Write integration tests for server actions
|
|
310
|
+
- Use `data-testid` for E2E
|
|
311
|
+
- Mock external dependencies
|
|
312
|
+
- Keep tests deterministic
|
|
313
|
+
|
|
314
|
+
**Don't:**
|
|
315
|
+
- Don't test implementation details
|
|
316
|
+
- Don't duplicate coverage in E2E
|
|
317
|
+
- Don't use `sleep()` in E2E
|
|
318
|
+
- Don't share mutable state between tests
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Frontend Conventions (UI, state, feedback)
|
|
2
|
+
|
|
3
|
+
Our preferences for building UI in this stack — *which patterns we reach for and why*. The **components themselves come from the `shadcn` skill** (component selection + composition rules); this file is the convention layer on top. Server/data architecture lives in [conventions.md](conventions.md) and [server-actions.md](server-actions.md).
|
|
4
|
+
|
|
5
|
+
> When a convention needs a component, defer to `shadcn`. When it needs a Server Action / DAL / auth, defer to this skill's core.
|
|
6
|
+
|
|
7
|
+
## URL state — `nuqs`
|
|
8
|
+
|
|
9
|
+
Prefer **URL search params (via `nuqs`)** for any UI state that should be shareable, refresh-safe, or readable on the server: list **filters, sort, pagination**, tab selection, search queries, and "open panel/dialog" state.
|
|
10
|
+
|
|
11
|
+
- **Why:** in the App Router, `searchParams` is readable in an RSC, so the server can filter/sort/paginate and the page is linkable and refresh-safe. Local `useState` for these loses on refresh and can't be server-rendered.
|
|
12
|
+
- Keep genuinely ephemeral state (hover, focus, uncommitted form text) in React state — not everything belongs in the URL.
|
|
13
|
+
- **Setup:** wrap the app once in `NuqsAdapter` (`nuqs/adapters/next/app`) in the root layout. Parse on the server with the `nuqs` server parsers; read/write on the client with `useQueryState` / `useQueryStates`.
|
|
14
|
+
- This is the same URL-state layer the data table uses → `shadcn` → `rules/data-table.md`.
|
|
15
|
+
|
|
16
|
+
## Data fetching & cache — RSC first, **SWR** for client
|
|
17
|
+
|
|
18
|
+
- **Default:** fetch on the server (RSC / DAL), mutate via Server Actions — no client fetch.
|
|
19
|
+
- **When you genuinely need client fetching** (polling, infinite scroll, data that changes outside the request, client-only widgets), use **SWR** for caching/revalidation.
|
|
20
|
+
- **Why:** SWR gives stale-while-revalidate, request dedup, and focus revalidation without hand-rolling a cache — but it's the *exception*, not the default (see [Core Principles](SKILL.md)).
|
|
21
|
+
- After a Server Action mutates server data, prefer `revalidatePath` / `revalidateTag`; call SWR `mutate()` only for client-cached keys.
|
|
22
|
+
|
|
23
|
+
## Async feedback — Progress/Skeleton for reads, **Sonner** for writes
|
|
24
|
+
|
|
25
|
+
- **Reads (queries / navigation / loading):** show a **Skeleton** or **Progress** placeholder (and `loading.tsx` / `Suspense` at route level). Never a toast for "loading."
|
|
26
|
+
- **Writes (mutations / Server Actions):** report the *result* with a **Sonner** toast — `toast.success(...)` on success, `toast.error(result.error?.message)` on failure (the `ActionResult` shape in [server-actions.md](server-actions.md)). Pair with the button's `isPending` for the in-flight state.
|
|
27
|
+
- **Why:** loading is a *state of the page* → inline placeholder; a mutation result is a *transient event* → toast. Mixing them (toast for loading, inline text for a save result) reads wrong.
|
|
28
|
+
- Components (`Skeleton` / `Progress` / `Spinner` / `sonner`) are shadcn — see its "Feedback" selection + composition rules.
|
|
29
|
+
|
|
30
|
+
## File upload — drag-and-drop dropzone
|
|
31
|
+
|
|
32
|
+
- Prefer a **drag-and-drop dropzone** (with a click-to-browse fallback) over a bare `<input type="file">`.
|
|
33
|
+
- **Component:** use the shadcn-registry dropzone / file-upload component → `shadcn` skill (add via its CLI, then fix imports to the project aliases).
|
|
34
|
+
- **Upload handling:** send to a **Server Action** or a `route.ts` handler; validate type/size with **Zod** at the boundary; store via the project's storage client. Show per-file **Progress** and a **Sonner** toast on done/fail.
|
|
35
|
+
- Keep the upload action in the use-case layer (`actions.ts`) and the storage call in a `lib` client — same layering as [conventions.md](conventions.md).
|
|
36
|
+
|
|
37
|
+
## Portal app shell — sidebar + header
|
|
38
|
+
|
|
39
|
+
The standard layout for an authenticated portal/dashboard:
|
|
40
|
+
|
|
41
|
+
- **Sidebar** for primary navigation (collapsible) — the shadcn `Sidebar` block.
|
|
42
|
+
- **Header**, right-aligned, carries three controls: a **theme toggle**, a **locale (i18n) switcher**, and a **profile menu** (`DropdownMenu`) showing the signed-in user + sign-out.
|
|
43
|
+
- Profile data + sign-out come from the **session (better-auth)** — load the session in the **RSC layout** and pass primitives down; don't fetch it client-side.
|
|
44
|
+
- Theme toggle via `next-themes`; the i18n switcher drives the locale → see [Internationalization](#internationalization-i18n) below.
|
|
45
|
+
- Put the shell in a **route-group layout** (e.g. `app/(portal)/layout.tsx`) so every portal page inherits sidebar + header.
|
|
46
|
+
- The components (Sidebar, DropdownMenu, Button) and their composition rules live in `shadcn`; this is just the *arrangement we standardize on*.
|
|
47
|
+
|
|
48
|
+
## Internationalization (i18n)
|
|
49
|
+
|
|
50
|
+
When the app is multi-locale:
|
|
51
|
+
|
|
52
|
+
- **Library:** use an App Router–native i18n library (e.g. `next-intl`) so messages are **server-readable in RSC**, not a client-only context that re-renders the tree.
|
|
53
|
+
- **Locale routing:** prefer a `[locale]` route segment (`app/[locale]/...`) — the locale is in the URL, so it's shareable, server-rendered, and SEO-correct. Middleware negotiates and redirects to a default locale.
|
|
54
|
+
- **Messages:** per-locale catalogs (e.g. `messages/en.json`, `messages/zh.json`), namespaced by feature (not one flat file); load the active locale once in the root layout and provide it.
|
|
55
|
+
- **The header switcher** (the i18n button in the app shell) changes the active locale by pushing the new `[locale]` segment (or a locale cookie). If you keep locale as a search param instead of a segment, that's the [URL state](#url-state--nuqs) convention.
|
|
56
|
+
- **Translate at the edges, not in the DAL:** the DAL/use-case layer returns stable keys and data; UI resolves copy via the i18n hook / `getTranslations`. Don't bake localized strings into Server Actions or repositories (keeps the DAL framework-agnostic, per [conventions.md](conventions.md)).
|
|
57
|
+
|
|
58
|
+
## List / index pages
|
|
59
|
+
|
|
60
|
+
- Default to a **data table with filter + sort + pagination** for any portal list/index page (users, orders, records…), **not** a hand-rolled list — and drive its state through URL params (`nuqs`, above) so it's server-rendered and shareable.
|
|
61
|
+
- **Implementation:** `shadcn` → `rules/data-table.md` (DiceUI `@diceui/data-table` for server-side; plain `Table` only for a trivial static list).
|