opencode-skills-collection 3.1.0 → 3.1.1
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/bundled-skills/.antigravity-install-manifest.json +84 -1
- package/bundled-skills/android-ui-journey-testing/SKILL.md +191 -0
- package/bundled-skills/ask-matt/SKILL.md +92 -0
- package/bundled-skills/bugs-are-annoying/SKILL.md +137 -0
- package/bundled-skills/codebase-design/DEEPENING.md +37 -0
- package/bundled-skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/bundled-skills/codebase-design/SKILL.md +145 -0
- package/bundled-skills/competitor-analysis/LICENSE.txt +21 -0
- package/bundled-skills/competitor-analysis/SKILL.md +434 -0
- package/bundled-skills/competitor-analysis/references/battle-card-subagent.md +127 -0
- package/bundled-skills/competitor-analysis/references/battle-card.md +91 -0
- package/bundled-skills/competitor-analysis/references/example-research.md +130 -0
- package/bundled-skills/competitor-analysis/references/report-template.html +127 -0
- package/bundled-skills/competitor-analysis/references/research-patterns.md +217 -0
- package/bundled-skills/competitor-analysis/references/workflow.md +434 -0
- package/bundled-skills/competitor-analysis/scripts/capture_screenshots.mjs +142 -0
- package/bundled-skills/competitor-analysis/scripts/compile_report.mjs +929 -0
- package/bundled-skills/competitor-analysis/scripts/extract_vs_names.mjs +140 -0
- package/bundled-skills/competitor-analysis/scripts/gate_candidates.mjs +194 -0
- package/bundled-skills/competitor-analysis/scripts/list_urls.mjs +90 -0
- package/bundled-skills/competitor-analysis/scripts/md_utils.mjs +50 -0
- package/bundled-skills/competitor-analysis/scripts/merge_partials.mjs +291 -0
- package/bundled-skills/competitor-analysis/scripts/package.json +6 -0
- package/bundled-skills/design-it/3d-ui/SKILL.md +259 -0
- package/bundled-skills/design-it/SKILL.md +170 -0
- package/bundled-skills/design-it/ai-native-ui/SKILL.md +295 -0
- package/bundled-skills/design-it/aurora-ui/SKILL.md +307 -0
- package/bundled-skills/design-it/bento-ui/SKILL.md +314 -0
- package/bundled-skills/design-it/brutalism/SKILL.md +270 -0
- package/bundled-skills/design-it/brutalist-typography/SKILL.md +287 -0
- package/bundled-skills/design-it/card-based-design/SKILL.md +262 -0
- package/bundled-skills/design-it/claymorphism/SKILL.md +287 -0
- package/bundled-skills/design-it/color-blocking/SKILL.md +278 -0
- package/bundled-skills/design-it/command-center-ui/SKILL.md +345 -0
- package/bundled-skills/design-it/cyber-y2k/SKILL.md +312 -0
- package/bundled-skills/design-it/cyberpunk-ui/SKILL.md +262 -0
- package/bundled-skills/design-it/dark-mode/SKILL.md +289 -0
- package/bundled-skills/design-it/dashboard-design/SKILL.md +331 -0
- package/bundled-skills/design-it/data-dense-design/SKILL.md +322 -0
- package/bundled-skills/design-it/duotone-design/SKILL.md +248 -0
- package/bundled-skills/design-it/editorial-design/SKILL.md +328 -0
- package/bundled-skills/design-it/flat-design/SKILL.md +221 -0
- package/bundled-skills/design-it/flat-design-2/SKILL.md +240 -0
- package/bundled-skills/design-it/floating-ui/SKILL.md +299 -0
- package/bundled-skills/design-it/frutiger-aero/SKILL.md +274 -0
- package/bundled-skills/design-it/glassmorphism/SKILL.md +272 -0
- package/bundled-skills/design-it/gradient-design/SKILL.md +309 -0
- package/bundled-skills/design-it/high-contrast/SKILL.md +288 -0
- package/bundled-skills/design-it/holographic-ui/SKILL.md +310 -0
- package/bundled-skills/design-it/isometric-design/SKILL.md +228 -0
- package/bundled-skills/design-it/layered-design/SKILL.md +247 -0
- package/bundled-skills/design-it/material-design/SKILL.md +275 -0
- package/bundled-skills/design-it/maximalism/SKILL.md +297 -0
- package/bundled-skills/design-it/minimalism/SKILL.md +267 -0
- package/bundled-skills/design-it/monochromatic-ui/SKILL.md +296 -0
- package/bundled-skills/design-it/neo-brutalism/SKILL.md +270 -0
- package/bundled-skills/design-it/neumorphism/SKILL.md +248 -0
- package/bundled-skills/design-it/retro-design/SKILL.md +283 -0
- package/bundled-skills/design-it/retro-futurism/SKILL.md +259 -0
- package/bundled-skills/design-it/sci-fi-interface/SKILL.md +309 -0
- package/bundled-skills/design-it/skeuomorphism/SKILL.md +280 -0
- package/bundled-skills/design-it/soft-pastel/SKILL.md +307 -0
- package/bundled-skills/design-it/spatial-computing-ui/SKILL.md +300 -0
- package/bundled-skills/design-it/spatial-design/SKILL.md +268 -0
- package/bundled-skills/design-it/swiss-design/SKILL.md +293 -0
- package/bundled-skills/design-it/synthwave/SKILL.md +257 -0
- package/bundled-skills/design-it/tile-design/SKILL.md +297 -0
- package/bundled-skills/design-it/typography-first/SKILL.md +247 -0
- package/bundled-skills/design-it/vaporwave/SKILL.md +331 -0
- package/bundled-skills/design-it/vibrant-maximalism/SKILL.md +291 -0
- package/bundled-skills/design-it/widget-based-design/SKILL.md +274 -0
- package/bundled-skills/design-it/y2k-design/SKILL.md +268 -0
- package/bundled-skills/diagnosing-bugs/SKILL.md +165 -0
- package/bundled-skills/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
- package/bundled-skills/docs/contributors/skill-scoring.md +235 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/bundled-skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/bundled-skills/domain-modeling/SKILL.md +105 -0
- package/bundled-skills/grill-me/SKILL.md +36 -0
- package/bundled-skills/grill-with-docs/SKILL.md +36 -0
- package/bundled-skills/grilling/SKILL.md +39 -0
- package/bundled-skills/handoff/SKILL.md +45 -0
- package/bundled-skills/image-generator/.env.example +7 -0
- package/bundled-skills/image-generator/SKILL.md +509 -0
- package/bundled-skills/improve-codebase-architecture/HTML-REPORT.md +123 -0
- package/bundled-skills/improve-codebase-architecture/SKILL.md +97 -0
- package/bundled-skills/learn/SKILL.md +156 -0
- package/bundled-skills/lesson-generator/SKILL.md +90 -0
- package/bundled-skills/llm-council/.env.example +7 -0
- package/bundled-skills/llm-council/SKILL.md +602 -0
- package/bundled-skills/loop-library/SKILL.md +205 -0
- package/bundled-skills/loop-library/agents/openai.yaml +4 -0
- package/bundled-skills/loop-library/references/catalog.md +270 -0
- package/bundled-skills/mailtrap-managing-contacts/SKILL.md +112 -0
- package/bundled-skills/mailtrap-sending-emails/SKILL.md +167 -0
- package/bundled-skills/mailtrap-setting-up-sending-domain/SKILL.md +77 -0
- package/bundled-skills/mailtrap-testing-with-sandbox/SKILL.md +110 -0
- package/bundled-skills/prototype/LOGIC.md +79 -0
- package/bundled-skills/prototype/SKILL.md +62 -0
- package/bundled-skills/prototype/UI.md +112 -0
- package/bundled-skills/setup-matt-pocock-skills/SKILL.md +158 -0
- package/bundled-skills/setup-matt-pocock-skills/domain.md +51 -0
- package/bundled-skills/setup-matt-pocock-skills/issue-tracker-github.md +34 -0
- package/bundled-skills/setup-matt-pocock-skills/issue-tracker-gitlab.md +35 -0
- package/bundled-skills/setup-matt-pocock-skills/issue-tracker-local.md +19 -0
- package/bundled-skills/setup-matt-pocock-skills/triage-labels.md +15 -0
- package/bundled-skills/survey-generator/LICENSE +21 -0
- package/bundled-skills/survey-generator/SKILL.md +143 -0
- package/bundled-skills/survey-generator/build_artifact.py +208 -0
- package/bundled-skills/survey-generator/examples/agentic-engineering/research_bundle.json +1196 -0
- package/bundled-skills/survey-generator/examples/agentic-engineering/survey.html +706 -0
- package/bundled-skills/survey-generator/style_spec.json +85 -0
- package/bundled-skills/survey-generator/templates/research_bundle_template.json +69 -0
- package/bundled-skills/tdd/SKILL.md +139 -0
- package/bundled-skills/tdd/mocking.md +59 -0
- package/bundled-skills/tdd/refactoring.md +10 -0
- package/bundled-skills/tdd/tests.md +61 -0
- package/bundled-skills/teach/GLOSSARY-FORMAT.md +35 -0
- package/bundled-skills/teach/LEARNING-RECORD-FORMAT.md +46 -0
- package/bundled-skills/teach/MISSION-FORMAT.md +31 -0
- package/bundled-skills/teach/RESOURCES-FORMAT.md +32 -0
- package/bundled-skills/teach/SKILL.md +169 -0
- package/bundled-skills/to-issues/SKILL.md +115 -0
- package/bundled-skills/to-prd/SKILL.md +104 -0
- package/bundled-skills/tools-page-seo-optimizer/SKILL.md +616 -0
- package/bundled-skills/triage/AGENT-BRIEF.md +207 -0
- package/bundled-skills/triage/OUT-OF-SCOPE.md +105 -0
- package/bundled-skills/triage/SKILL.md +143 -0
- package/bundled-skills/vibecode-production-qa-validator/SKILL.md +371 -141
- package/bundled-skills/wiki-builder/SKILL.md +157 -0
- package/bundled-skills/wiki-builder/agents/openai.yaml +5 -0
- package/bundled-skills/wiki-builder/references/wiki-flavors.md +98 -0
- package/bundled-skills/wiki-builder/scripts/init_wiki.sh +105 -0
- package/bundled-skills/wiki-builder/templates/index.md +20 -0
- package/bundled-skills/wiki-builder/templates/maintenance-log.md +7 -0
- package/bundled-skills/wiki-builder/templates/prompts/compile-concept-page.md +12 -0
- package/bundled-skills/wiki-builder/templates/prompts/compile-index.md +11 -0
- package/bundled-skills/wiki-builder/templates/prompts/compile-source-page.md +12 -0
- package/bundled-skills/wiki-builder/templates/prompts/lint-wiki.md +10 -0
- package/bundled-skills/wiki-builder/templates/prompts/query-and-file.md +11 -0
- package/bundled-skills/wiki-builder/templates/sources.md +9 -0
- package/bundled-skills/wiki-builder/templates/wiki.config.md +53 -0
- package/bundled-skills/writing-great-skills/GLOSSARY.md +181 -0
- package/bundled-skills/writing-great-skills/SKILL.md +111 -0
- package/bundled-skills/yao-meta-skill/SKILL.md +86 -0
- package/bundled-skills/yao-meta-skill/agents/interface.yaml +26 -0
- package/bundled-skills/yao-meta-skill/manifest.json +24 -0
- package/bundled-skills/yao-meta-skill/references/artifact-design-doctrine.md +49 -0
- package/bundled-skills/yao-meta-skill/references/authoring-discipline.md +78 -0
- package/bundled-skills/yao-meta-skill/references/autonomous-adaptation.md +65 -0
- package/bundled-skills/yao-meta-skill/references/distribution-registry-method.md +60 -0
- package/bundled-skills/yao-meta-skill/references/eval-playbook.md +69 -0
- package/bundled-skills/yao-meta-skill/references/gate-selection.md +68 -0
- package/bundled-skills/yao-meta-skill/references/governance.md +134 -0
- package/bundled-skills/yao-meta-skill/references/human-review-template.md +54 -0
- package/bundled-skills/yao-meta-skill/references/intent-dialogue.md +138 -0
- package/bundled-skills/yao-meta-skill/references/iteration-philosophy.md +30 -0
- package/bundled-skills/yao-meta-skill/references/non-skill-decision-tree.md +39 -0
- package/bundled-skills/yao-meta-skill/references/operating-modes.md +107 -0
- package/bundled-skills/yao-meta-skill/references/output-eval-method.md +113 -0
- package/bundled-skills/yao-meta-skill/references/output-quality-risk.md +41 -0
- package/bundled-skills/yao-meta-skill/references/output-visual-quality.md +53 -0
- package/bundled-skills/yao-meta-skill/references/packaging-contracts.md +70 -0
- package/bundled-skills/yao-meta-skill/references/pattern-extraction-doctrine.md +76 -0
- package/bundled-skills/yao-meta-skill/references/platform-capability-matrix.md +49 -0
- package/bundled-skills/yao-meta-skill/references/prompt-engineering-doctrine.md +76 -0
- package/bundled-skills/yao-meta-skill/references/qa-ladder.md +57 -0
- package/bundled-skills/yao-meta-skill/references/reference-scan.md +126 -0
- package/bundled-skills/yao-meta-skill/references/regression-cause-taxonomy.md +80 -0
- package/bundled-skills/yao-meta-skill/references/resource-boundaries.md +120 -0
- package/bundled-skills/yao-meta-skill/references/review-studio-method.md +87 -0
- package/bundled-skills/yao-meta-skill/references/review-waiver-method.md +76 -0
- package/bundled-skills/yao-meta-skill/references/runtime-conformance-method.md +21 -0
- package/bundled-skills/yao-meta-skill/references/skill-archetypes.md +86 -0
- package/bundled-skills/yao-meta-skill/references/skill-atlas-method.md +35 -0
- package/bundled-skills/yao-meta-skill/references/skill-engineering-method.md +210 -0
- package/bundled-skills/yao-meta-skill/references/skill-ir-method.md +41 -0
- package/bundled-skills/yao-meta-skill/references/skillops-decision-policy.md +53 -0
- package/bundled-skills/yao-meta-skill/references/systems-thinking-doctrine.md +75 -0
- package/bundled-skills/yao-meta-skill/references/telemetry-drift-method.md +182 -0
- package/bundled-skills/yao-meta-skill/references/trust-security-method.md +79 -0
- package/bundled-skills/yao-meta-skill/references/user-memory-policy.md +35 -0
- package/bundled-skills/youtube-notetaker/SKILL.md +209 -0
- package/bundled-skills/youtube-notetaker/reference/artifact.html +269 -0
- package/bundled-skills/youtube-notetaker/scripts/contact_sheet.py +53 -0
- package/bundled-skills/youtube-notetaker/scripts/detect_slides.sh +19 -0
- package/bundled-skills/youtube-notetaker/scripts/download.sh +24 -0
- package/bundled-skills/youtube-notetaker/scripts/extract_slides.py +43 -0
- package/bundled-skills/youtube-notetaker/scripts/serve.py +173 -0
- package/bundled-skills/youtube-notetaker/scripts/setup.sh +27 -0
- package/bundled-skills/youtube-notetaker/scripts/verify.sh +31 -0
- package/bundled-skills/youtube-notetaker/scripts/vtt_to_transcript.py +59 -0
- package/bundled-skills/youtube-notetaker/scripts/write_library_item.py +69 -0
- package/package.json +1 -1
- package/skills_index.json +1956 -286
- package/bundled-skills/ai-md/SKILL.md +0 -523
- package/bundled-skills/atlas-contract/SKILL.md +0 -650
- package/bundled-skills/busybox-on-windows/SKILL.md +0 -40
- package/bundled-skills/monte-carlo-prevent/SKILL.md +0 -257
- package/bundled-skills/monte-carlo-prevent/references/TROUBLESHOOTING.md +0 -23
- package/bundled-skills/monte-carlo-prevent/references/parameters.md +0 -32
- package/bundled-skills/monte-carlo-prevent/references/workflows.md +0 -478
- package/bundled-skills/monte-carlo-push-ingestion/SKILL.md +0 -372
- package/bundled-skills/monte-carlo-push-ingestion/references/anomaly-detection.md +0 -87
- package/bundled-skills/monte-carlo-push-ingestion/references/custom-lineage.md +0 -203
- package/bundled-skills/monte-carlo-push-ingestion/references/direct-http-api.md +0 -207
- package/bundled-skills/monte-carlo-push-ingestion/references/prerequisites.md +0 -150
- package/bundled-skills/monte-carlo-push-ingestion/references/push-lineage.md +0 -160
- package/bundled-skills/monte-carlo-push-ingestion/references/push-metadata.md +0 -158
- package/bundled-skills/monte-carlo-push-ingestion/references/push-query-logs.md +0 -219
- package/bundled-skills/monte-carlo-push-ingestion/references/validation.md +0 -257
- package/bundled-skills/monte-carlo-push-ingestion/scripts/sample_verify.py +0 -357
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_and_push_lineage.py +0 -70
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_and_push_metadata.py +0 -65
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_and_push_query_logs.py +0 -70
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_lineage.py +0 -214
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_metadata.py +0 -160
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_query_logs.py +0 -164
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/push_lineage.py +0 -198
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/push_metadata.py +0 -193
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/push_query_logs.py +0 -207
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_and_push_metadata.py +0 -71
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_and_push_query_logs.py +0 -64
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_metadata.py +0 -253
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_query_logs.py +0 -149
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/push_metadata.py +0 -190
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/push_query_logs.py +0 -208
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_and_push_lineage.py +0 -83
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_and_push_metadata.py +0 -77
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_and_push_query_logs.py +0 -83
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_lineage.py +0 -240
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_metadata.py +0 -212
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_query_logs.py +0 -204
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/push_lineage.py +0 -192
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/push_metadata.py +0 -178
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/push_query_logs.py +0 -200
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_and_push_lineage.py +0 -119
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_and_push_metadata.py +0 -119
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_and_push_query_logs.py +0 -117
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_lineage.py +0 -265
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_metadata.py +0 -313
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_query_logs.py +0 -284
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/push_lineage.py +0 -309
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/push_metadata.py +0 -245
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/push_query_logs.py +0 -255
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_and_push_lineage.py +0 -78
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_and_push_metadata.py +0 -80
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_and_push_query_logs.py +0 -88
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_lineage.py +0 -235
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_metadata.py +0 -219
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_query_logs.py +0 -239
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/push_lineage.py +0 -178
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/push_metadata.py +0 -178
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/push_query_logs.py +0 -196
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_and_push_lineage.py +0 -154
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_and_push_metadata.py +0 -137
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_and_push_query_logs.py +0 -137
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_lineage.py +0 -349
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_metadata.py +0 -329
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_query_logs.py +0 -254
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/push_lineage.py +0 -307
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/push_metadata.py +0 -228
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/push_query_logs.py +0 -248
- package/bundled-skills/monte-carlo-push-ingestion/scripts/test_template_sdk_usage.py +0 -340
- package/bundled-skills/skill-optimizer/SKILL.md +0 -271
- package/bundled-skills/using-superpowers/SKILL.md +0 -98
|
@@ -1,238 +1,468 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: vibecode-production-qa-validator
|
|
3
|
-
description: "
|
|
3
|
+
description: "13-phase production QA for fullstack Next.js apps: build verification, SEO tags, OG images, favicon, route regression, API auth, page speed, lazy load, vulnerability scan, UI/UX cards, error boundaries, database, secure rendering, and cleanup."
|
|
4
4
|
category: devops
|
|
5
5
|
risk: safe
|
|
6
6
|
source: self
|
|
7
7
|
source_type: self
|
|
8
8
|
date_added: "2026-05-31"
|
|
9
9
|
author: Whoisabhishekadhikari
|
|
10
|
-
tags: [qa,
|
|
11
|
-
tools: [claude, cursor, gemini, claude-code]
|
|
12
|
-
version:
|
|
10
|
+
tags: [qa, nextjs, production, deployment, seo, authentication, api, performance, favicon, cleanup, lighthouse, database, security, ui-ux]
|
|
11
|
+
tools: [claude, cursor, gemini, claude-code, opencode]
|
|
12
|
+
version: 2.0.0
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
# Production QA Validator
|
|
15
|
+
# Production QA Validator
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Run phases in order. Fix failures before moving to next.
|
|
18
|
+
|
|
19
|
+
## When to Use
|
|
20
|
+
|
|
21
|
+
- Use before shipping or promoting a fullstack Next.js app to production.
|
|
22
|
+
- Use after large UI, SEO, auth, API, database, or dependency changes need a concrete launch-readiness pass.
|
|
23
|
+
- Use when you need a compact command-driven checklist for build, route, metadata, performance, security, and cleanup checks.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
export PROD_URL="https://yourdomain.com"
|
|
27
|
+
export QA_AUTH_HEADER="" # optional: "Bearer eyJ..."
|
|
28
|
+
export PAGESPEED_API_KEY="" # optional: for auto PageSpeed API
|
|
29
|
+
```
|
|
18
30
|
|
|
19
31
|
---
|
|
20
32
|
|
|
21
|
-
##
|
|
33
|
+
## Consolidated Runner
|
|
22
34
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
```bash
|
|
36
|
+
qa:all() { qa:code && qa:build && qa:routes / /about /contact /privacy /terms /faq /sitemap.xml /robots.txt /api/health && qa:seo && qa:api /api/health /api/tools && qa:git && qa:smoke; }
|
|
37
|
+
qa:full() { qa:all && qa:auth && qa:auth:cookies && qa:lazyload && qa:heavyload && qa:vulns && qa:cleanup && qa:ux:cards && qa:ux:boundaries && qa:ux:animation && qa:database && qa:secure; }
|
|
38
|
+
```
|
|
26
39
|
|
|
27
40
|
---
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
### Phase 1: Code Integrity
|
|
30
43
|
|
|
31
|
-
|
|
44
|
+
- [ ] `npx tsc --noEmit`
|
|
45
|
+
- [ ] `npx eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0`
|
|
46
|
+
- [ ] `npm test -- --runInBand --passWithNoTests`
|
|
32
47
|
|
|
33
48
|
```bash
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
# 2. Custom validation scripts (if present)
|
|
38
|
-
npm run validate 2>/dev/null || echo "No validate script"
|
|
49
|
+
qa:code() { npx tsc --noEmit && npx eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0 && npm test -- --runInBand --passWithNoTests; }
|
|
50
|
+
```
|
|
39
51
|
|
|
40
|
-
|
|
41
|
-
npm run lint:canon 2>/dev/null || echo "No canon lint"
|
|
42
|
-
npm run lint:anchors 2>/dev/null || echo "No anchor lint"
|
|
43
|
-
npm run lint:links 2>/dev/null || echo "No link lint"
|
|
52
|
+
---
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
npx eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0
|
|
54
|
+
### Phase 2: Build Verification
|
|
47
55
|
|
|
48
|
-
|
|
49
|
-
|
|
56
|
+
- [ ] `npm run build` succeeds
|
|
57
|
+
- [ ] SEO pages show `○`/`●` not `λ`
|
|
58
|
+
- [ ] Build log has no errors
|
|
50
59
|
|
|
51
|
-
|
|
52
|
-
npm run build
|
|
60
|
+
```bash
|
|
61
|
+
qa:build() { npm run build 2>&1 | tee /tmp/qa-build.log && ! grep -qi "error\|failed" /tmp/qa-build.log; }
|
|
53
62
|
```
|
|
54
63
|
|
|
55
|
-
|
|
64
|
+
| Symbol | Meaning |
|
|
65
|
+
|--------|---------|
|
|
66
|
+
| `○` | Static |
|
|
67
|
+
| `●` | SSG |
|
|
68
|
+
| `λ` | Dynamic/serverless |
|
|
69
|
+
| `⊕` | Partial prerender |
|
|
56
70
|
|
|
57
71
|
---
|
|
58
72
|
|
|
59
|
-
|
|
73
|
+
### Phase 3: API Session & Authentication
|
|
74
|
+
|
|
75
|
+
- [ ] Auth endpoints respond (login, session, logout)
|
|
76
|
+
- [ ] Protected routes return 401/403
|
|
77
|
+
- [ ] Session cookie: HttpOnly + Secure + SameSite
|
|
78
|
+
- [ ] Cookie not expired, Path/Domain correct
|
|
79
|
+
- [ ] No rate limiting bypass
|
|
60
80
|
|
|
61
81
|
```bash
|
|
62
|
-
|
|
82
|
+
qa:auth() {
|
|
83
|
+
local F=0
|
|
84
|
+
for ep in /api/auth/login /api/auth/session /api/auth/logout; do
|
|
85
|
+
curl -so /dev/null -w "%{http_code}" "$PROD_URL$ep" | grep -q "200\|401" || { echo " ✗ $ep unreachable"; ((F++)); }
|
|
86
|
+
done
|
|
87
|
+
curl -so /dev/null -w "%{http_code}" "$PROD_URL/api/protected" | grep -q "401\|403" || echo " ⚠ Protected route not denying unauthenticated"
|
|
88
|
+
return $F
|
|
89
|
+
}
|
|
90
|
+
qa:auth:cookies() {
|
|
91
|
+
for ep in /api/auth/session /api/auth/login; do
|
|
92
|
+
curl -sI "$PROD_URL$ep" | grep -i "^set-cookie:" | while IFS= read -r c; do
|
|
93
|
+
echo " $ep: $(echo "$c" | cut -d= -f1)"
|
|
94
|
+
echo "$c" | grep -qi "HttpOnly" || echo " ✗ Missing HttpOnly"
|
|
95
|
+
echo "$c" | grep -qi "Secure" || echo " ✗ Missing Secure"
|
|
96
|
+
echo "$c" | grep -qi "SameSite" || echo " ⚠ Missing SameSite"
|
|
97
|
+
done
|
|
98
|
+
done
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
63
103
|
|
|
64
|
-
|
|
65
|
-
grep -i "error\|failed\|cannot" build.log | grep -v "no errors"
|
|
104
|
+
### Phase 4: Route Regression
|
|
66
105
|
|
|
67
|
-
|
|
68
|
-
|
|
106
|
+
- [ ] Core pages, sitemap, robots.txt all 200
|
|
107
|
+
- [ ] URLs use kebab-case, no duplicate slugs
|
|
108
|
+
- [ ] robots.txt allows indexing
|
|
109
|
+
- [ ] Sitemap XML valid, all URLs resolve 200
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
qa:routes() { local F=0; for p; do local C=$(curl -so /dev/null -w "%{http_code}" "$PROD_URL$p"); echo "$C $p"; [ "$C" = "200" ] || ((F++)); done; return $F; }
|
|
113
|
+
qa:robots() { curl -s "$PROD_URL/robots.txt" | grep -qi "Disallow: /$" && echo " ✗ Blocks all crawlers" || echo " ✓ OK"; }
|
|
114
|
+
qa:sitemap() { curl -s "$PROD_URL/sitemap.xml" | python3 -c "import sys,xml.etree.ElementTree as ET; ET.parse(sys.stdin); print('✓ Valid XML')"; }
|
|
69
115
|
```
|
|
70
116
|
|
|
71
|
-
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### Phase 5: SEO — Tags, Images, Favicon, Slugs
|
|
72
120
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
121
|
+
- [ ] `<title>` 30–60 chars, unique per page
|
|
122
|
+
- [ ] `<meta name="description">` in raw HTML
|
|
123
|
+
- [ ] og:title matches `<title>`, og:url matches canonical
|
|
124
|
+
- [ ] og:image ≥ 1200×630px, absolute URL, loads 200
|
|
125
|
+
- [ ] twitter:card = summary_large_image
|
|
126
|
+
- [ ] Canonical self-referencing, no duplicates
|
|
127
|
+
- [ ] `/favicon.ico` 200, apple-touch-icon present
|
|
128
|
+
- [ ] `hreflang` tags if multilingual
|
|
129
|
+
- [ ] JSON-LD structured data present
|
|
130
|
+
- [ ] Slugs: kebab-case, < 80 chars, no stop words
|
|
79
131
|
|
|
80
|
-
|
|
132
|
+
```bash
|
|
133
|
+
qa:seo() {
|
|
134
|
+
local H=$(curl -s "$PROD_URL"); local F=0
|
|
135
|
+
for t in "og:title" "og:description" "og:image" "twitter:card" "canonical" "description"; do echo "$H" | grep -qi "$t" || { echo " ✗ $t"; ((F++)); }; done
|
|
136
|
+
echo "$H" | grep -qi "<title>" || { echo " ✗ <title>"; ((F++)); }
|
|
137
|
+
local T=$(echo "$H" | grep -oP '<title>\K[^<]+'); local L=${#T}; [ $L -ge 30 -a $L -le 60 ] || echo " ⚠ Title ${L}chars (target 30-60)"
|
|
138
|
+
curl -so /dev/null -w "%{http_code}" "$PROD_URL/favicon.ico" | grep -q 200 || echo " ⚠ No favicon.ico"
|
|
139
|
+
return $F
|
|
140
|
+
}
|
|
141
|
+
qa:seo:ogimage() {
|
|
142
|
+
local I=$(curl -s "$PROD_URL" | grep -oP 'og:image" content="\K[^"]+'); [[ "$I" =~ ^http ]] || I="$PROD_URL$I"
|
|
143
|
+
curl -so /dev/null -w "%{http_code}" "$I" | grep -q 200 || { echo " ✗ og:image returns non-200"; return 1; }
|
|
144
|
+
command -v identify &>/dev/null && curl -s "$I" | identify -format "%wx%h" - 2>/dev/null | grep -qP "12\d{2}x6\d{2}" && echo " ✓ ≥ 1200x630" || echo " ⚠ Install imagemagick to check dimensions"
|
|
145
|
+
}
|
|
146
|
+
```
|
|
81
147
|
|
|
82
148
|
---
|
|
83
149
|
|
|
84
|
-
|
|
150
|
+
### Phase 6: API Route Behavior
|
|
85
151
|
|
|
86
|
-
|
|
152
|
+
- [ ] Correct status codes + Content-Type
|
|
153
|
+
- [ ] Errors return consistent JSON `{ error, message }`
|
|
154
|
+
- [ ] Response times < 200ms
|
|
155
|
+
- [ ] CORS headers correct (if cross-origin)
|
|
87
156
|
|
|
88
157
|
```bash
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
# <meta name="twitter:card" content="summary_large_image" />
|
|
98
|
-
# <link rel="canonical" href="https://..." />
|
|
99
|
-
# <meta name="description" content="..." />
|
|
158
|
+
qa:api() {
|
|
159
|
+
for p; do
|
|
160
|
+
local R=$(curl -so /dev/null -w "%{http_code} %{content_type}" "$PROD_URL$p")
|
|
161
|
+
echo " $p → $R"
|
|
162
|
+
done
|
|
163
|
+
local E=$(curl -s "$PROD_URL/api/nonexistent")
|
|
164
|
+
echo "$E" | python3 -c "import sys,json; d=json.load(sys.stdin); assert 'error' in d; print('✓ Consistent errors')" 2>/dev/null || echo " ⚠ Inconsistent error shape"
|
|
165
|
+
}
|
|
100
166
|
```
|
|
101
167
|
|
|
102
|
-
If tags are missing from raw HTML: they're added by client-side JavaScript. Fix: move to `export const metadata` or `generateMetadata`.
|
|
103
|
-
|
|
104
168
|
---
|
|
105
169
|
|
|
106
|
-
|
|
170
|
+
### Phase 7: Git Hygiene
|
|
107
171
|
|
|
108
|
-
|
|
172
|
+
- [ ] No secrets/credentials in diff
|
|
173
|
+
- [ ] No `.next`/`node_modules` staged
|
|
174
|
+
- [ ] Commit: `type(scope): message`
|
|
109
175
|
|
|
110
176
|
```bash
|
|
111
|
-
|
|
177
|
+
qa:git() {
|
|
178
|
+
local S=$(git diff HEAD 2>/dev/null | grep -i "password\|secret\|api_key\|localhost:3000" | grep "^+")
|
|
179
|
+
[ -n "$S" ] && { echo " ✗ Secrets in diff!"; echo "$S"; return 1; } || echo " ✓ No secrets"
|
|
180
|
+
local A=$(git status --short 2>/dev/null | grep -E "\.next|node_modules" | head -3)
|
|
181
|
+
[ -n "$A" ] && echo " ⚠ Build artifacts:" && echo "$A" || echo " ✓ No artifacts"
|
|
182
|
+
}
|
|
183
|
+
```
|
|
112
184
|
|
|
113
|
-
|
|
114
|
-
for path in "/" "/about" "/contact" "/privacy" "/terms" "/faq"; do
|
|
115
|
-
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$BASE$path")
|
|
116
|
-
echo "$STATUS $BASE$path"
|
|
117
|
-
done
|
|
185
|
+
---
|
|
118
186
|
|
|
119
|
-
|
|
120
|
-
for path in "/sitemap.xml" "/robots.txt"; do
|
|
121
|
-
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$BASE$path")
|
|
122
|
-
echo "$STATUS $BASE$path"
|
|
123
|
-
done
|
|
187
|
+
### Phase 8: Post-Deployment Smoke Test
|
|
124
188
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
done
|
|
130
|
-
```
|
|
189
|
+
- [ ] Homepage 200, key pages 200
|
|
190
|
+
- [ ] OG image loads 200
|
|
191
|
+
- [ ] No console errors (manual)
|
|
192
|
+
- [ ] Auth flow works (manual)
|
|
131
193
|
|
|
132
|
-
|
|
194
|
+
```bash
|
|
195
|
+
qa:smoke() {
|
|
196
|
+
curl -sI "$PROD_URL" | head -1 | grep -q "200" && echo " ✓ Homepage" || echo " ✗ Homepage"
|
|
197
|
+
curl -sI "$PROD_URL/sitemap.xml" | head -1 | grep -q "200" && echo " ✓ Sitemap" || echo " ✗ Sitemap"
|
|
198
|
+
}
|
|
199
|
+
```
|
|
133
200
|
|
|
134
201
|
---
|
|
135
202
|
|
|
136
|
-
|
|
203
|
+
### Phase 9: Page Speed, Lazy Load & Bundles
|
|
137
204
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
except Exception as e:
|
|
146
|
-
print(f'✗ Invalid XML: {e}')
|
|
147
|
-
"
|
|
205
|
+
- [ ] Lighthouse ≥ 90 (Perf, A11y, SEO)
|
|
206
|
+
- [ ] FCP < 2.5s, LCP < 4.0s, CLS < 0.1
|
|
207
|
+
- [ ] Images lazy-loaded (`loading="lazy"`), WebP/AVIF
|
|
208
|
+
- [ ] Dynamic imports for heavy components
|
|
209
|
+
- [ ] Largest JS chunk < 200KB gzipped
|
|
210
|
+
- [ ] `font-display: swap`, no FOIT
|
|
211
|
+
- [ ] Total page weight < 1MB
|
|
148
212
|
|
|
149
|
-
|
|
150
|
-
|
|
213
|
+
```bash
|
|
214
|
+
qa:lazyload() {
|
|
215
|
+
local N=$(grep -r "loading=" app/ --include="*.tsx" 2>/dev/null | grep -c "lazy" || true)
|
|
216
|
+
echo " Lazy images: $N"
|
|
217
|
+
grep -rn "next/dynamic\|dynamic((" app/ --include="*.tsx" 2>/dev/null | head -5 | grep . || echo " ⚠ No dynamic imports"
|
|
218
|
+
}
|
|
219
|
+
qa:heavyload() {
|
|
220
|
+
ls -lhS .next/static/chunks/*.js 2>/dev/null | head -5
|
|
221
|
+
local W=$(curl -so /dev/null -w "%{size_download}" "$PROD_URL" 2>/dev/null || echo 0)
|
|
222
|
+
echo " HTML weight: ~$((W/1024))KB"
|
|
223
|
+
echo " ⚠ Run 'npx lighthouse $PROD_URL --view' for full weight analysis"
|
|
224
|
+
}
|
|
225
|
+
# PageSpeed: open "https://pagespeed.web.dev/?url=$PROD_URL"
|
|
151
226
|
```
|
|
152
227
|
|
|
153
228
|
---
|
|
154
229
|
|
|
155
|
-
|
|
230
|
+
### Phase 10: Cleanup & Vulnerability Scan
|
|
231
|
+
|
|
232
|
+
- [ ] `npm prune`, `depcheck` — no unused deps
|
|
233
|
+
- [ ] No console.log/debugger in staged code
|
|
234
|
+
- [ ] `npm audit` — zero critical/high vulnerabilities
|
|
235
|
+
- [ ] No eval/new Function/document.write
|
|
236
|
+
- [ ] TODOs resolved
|
|
156
237
|
|
|
157
238
|
```bash
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
239
|
+
qa:vulns() {
|
|
240
|
+
npm audit 2>/dev/null | grep -E "critical|high" | grep . && echo " ✗ Vulnerabilities!" || echo " ✓ No critical/high vulns"
|
|
241
|
+
npm outdated 2>/dev/null | head -5 | grep . || echo " ✓ All up to date"
|
|
242
|
+
local D=$(grep -rn "eval(\|new Function(\|document.write(" app/ src/ --include="*.ts" --include="*.tsx" 2>/dev/null | head -5)
|
|
243
|
+
[ -n "$D" ] && echo " ⚠ Dangerous patterns:" && echo "$D" || echo " ✓ No dangerous patterns"
|
|
244
|
+
}
|
|
245
|
+
qa:cleanup() {
|
|
246
|
+
local D=$(git diff --cached 2>/dev/null | grep "^+" | grep -i "console\.log\|debugger" | head -5)
|
|
247
|
+
[ -n "$D" ] && echo " ✗ Debug artifacts:" && echo "$D" || echo " ✓ No debug artifacts"
|
|
248
|
+
local T=$(git diff --cached 2>/dev/null | grep "^+" | grep -i "TODO\|FIXME\|HACK" | head -5)
|
|
249
|
+
[ -n "$T" ] && echo " ⚠ TODOs remain:" && echo "$T"
|
|
250
|
+
}
|
|
163
251
|
```
|
|
164
252
|
|
|
165
253
|
---
|
|
166
254
|
|
|
167
|
-
|
|
255
|
+
### Phase 11: UI/UX — Cards, Animation, Error Boundaries
|
|
168
256
|
|
|
169
|
-
|
|
257
|
+
- [ ] Cards: equal height grid, no overlap, text ellipsis, responsive (1→2→3 col)
|
|
258
|
+
- [ ] No horizontal scroll at any viewport (320–1440px)
|
|
259
|
+
- [ ] Images: consistent `aspect-ratio` + `object-fit: cover`
|
|
260
|
+
- [ ] Touch targets ≥ 44×44px
|
|
261
|
+
- [ ] Animations use `transform`+`opacity` only (not layout props)
|
|
262
|
+
- [ ] `prefers-reduced-motion` respected
|
|
263
|
+
- [ ] Error boundaries at root + route level (`app/error.tsx`, `app/global-error.tsx`)
|
|
264
|
+
- [ ] `app/not-found.tsx` and `app/loading.tsx` exist
|
|
265
|
+
- [ ] All client fetches show loading + error + empty states
|
|
266
|
+
- [ ] Buttons: hover, focus-visible, active, disabled, loading states
|
|
267
|
+
- [ ] Forms disable submit on click (no double-submit)
|
|
170
268
|
|
|
171
269
|
```bash
|
|
172
|
-
|
|
173
|
-
|
|
270
|
+
qa:ux:cards() {
|
|
271
|
+
local E=$(grep -rn "text-overflow\|line-clamp\|truncate" app/ --include="*.css" --include="*.tsx" 2>/dev/null | head -3)
|
|
272
|
+
[ -n "$E" ] && echo " ✓ Text overflow handling" || echo " ⚠ No text overflow handling"
|
|
273
|
+
local A=$(grep -rn "aspect-\|object-fit" app/ --include="*.css" --include="*.tsx" 2>/dev/null | head -3)
|
|
274
|
+
[ -n "$A" ] && echo " ✓ aspect-ratio/object-fit used" || echo " ⚠ No aspect-ratio set"
|
|
275
|
+
}
|
|
276
|
+
qa:ux:boundaries() {
|
|
277
|
+
for f in app/error.tsx app/global-error.tsx app/not-found.tsx app/loading.tsx; do
|
|
278
|
+
[ -f "$f" ] && echo " ✓ $f" || echo " ⚠ Missing $f"
|
|
279
|
+
done
|
|
280
|
+
}
|
|
281
|
+
qa:ux:animation() {
|
|
282
|
+
local A=$(grep -rn "animation.*width\|transition.*height\|@keyframes.*top\|@keyframes.*margin" app/ --include="*.css" --include="*.tsx" 2>/dev/null | head -5)
|
|
283
|
+
[ -n "$A" ] && echo " ⚠ Layout-triggering animations:" && echo "$A" || echo " ✓ No layout-triggering animations"
|
|
284
|
+
local P=$(grep -r "@media.*prefers-reduced-motion" app/ --include="*.css" --include="*.tsx" 2>/dev/null | head -3)
|
|
285
|
+
[ -n "$P" ] && echo " ✓ prefers-reduced-motion found in CSS" || echo " ⚠ No prefers-reduced-motion in CSS"
|
|
286
|
+
}
|
|
287
|
+
```
|
|
174
288
|
|
|
175
|
-
|
|
176
|
-
git diff HEAD | grep -i "password\|secret\|api_key\|localhost:3000" | grep "^+"
|
|
289
|
+
---
|
|
177
290
|
|
|
178
|
-
|
|
179
|
-
git status | grep -E "\.next|node_modules"
|
|
180
|
-
```
|
|
291
|
+
### Phase 12: Database & Data Layer
|
|
181
292
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
293
|
+
- [ ] Connection pool configured (no starvation)
|
|
294
|
+
- [ ] Schema in sync with migrations
|
|
295
|
+
- [ ] Indexes on all queried columns, no N+1
|
|
296
|
+
- [ ] No hardcoded DB credentials in source
|
|
297
|
+
- [ ] No raw SQL injection risk
|
|
298
|
+
- [ ] No sensitive data leaked in API responses
|
|
299
|
+
- [ ] Migrations are idempotent
|
|
185
300
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
301
|
+
```bash
|
|
302
|
+
qa:database() {
|
|
303
|
+
local H=$(grep -rn "postgres://\|mysql://\|mongodb://" app/ src/ --include="*.ts" --include="*.tsx" 2>/dev/null | grep -v ".env" | head -5)
|
|
304
|
+
[ -n "$H" ] && { echo " ✗ Hardcoded DB URL:"; echo "$H"; } || echo " ✓ No hardcoded DB URLs"
|
|
305
|
+
local R=$(grep -rn "\$queryRaw\|\.raw(" app/ src/ --include="*.ts" --include="*.tsx" 2>/dev/null | head -5)
|
|
306
|
+
[ -n "$R" ] && echo " ⚠ Raw SQL:" && echo "$R" || echo " ✓ No raw SQL"
|
|
307
|
+
local N=$(grep -rn "\.findMany\|\.findUnique" app/ src/ --include="*.ts" --include="*.tsx" 2>/dev/null | grep -v "include:" | head -5)
|
|
308
|
+
[ -n "$N" ] && echo " ⚠ Possible N+1:" && echo "$N" || echo " ✓ No N+1 patterns"
|
|
309
|
+
}
|
|
310
|
+
qa:db:migrations() {
|
|
311
|
+
[ -d "prisma/migrations" ] && echo " ✓ Prisma: $(ls prisma/migrations 2>/dev/null | wc -l) migrations" || echo " - No prisma migrations dir"
|
|
312
|
+
local M=$(ls db/migrations/*.sql 2>/dev/null | head -5); [ -n "$M" ] && echo " ✓ SQL migrations:" && echo "$M" || echo " - No SQL migration files"
|
|
313
|
+
}
|
|
190
314
|
```
|
|
191
315
|
|
|
192
316
|
---
|
|
193
317
|
|
|
194
|
-
|
|
318
|
+
### Phase 13: Secure Data Rendering
|
|
195
319
|
|
|
196
|
-
|
|
320
|
+
- [ ] No secrets/tokens in client source or localStorage
|
|
321
|
+
- [ ] No `dangerouslySetInnerHTML` without DOMPurify
|
|
322
|
+
- [ ] API errors don't leak stack traces
|
|
323
|
+
- [ ] Internal IDs use UUIDs not auto-increment
|
|
324
|
+
- [ ] User emails masked in UI
|
|
325
|
+
- [ ] NEXT_PUBLIC_ vars contain no secrets
|
|
197
326
|
|
|
198
327
|
```bash
|
|
199
|
-
|
|
328
|
+
qa:secure() {
|
|
329
|
+
local S=$(git grep -n "api_key\|API_KEY\|secret_key\|PRIVATE_KEY" -- ':!*.env*' ':!*test*' 2>/dev/null | head -5)
|
|
330
|
+
[ -n "$S" ] && echo " ✗ Secrets in source:" && echo "$S" || echo " ✓ No hardcoded secrets"
|
|
331
|
+
local D=$(grep -rn "dangerouslySetInnerHTML" app/ src/ --include="*.tsx" 2>/dev/null | head -5)
|
|
332
|
+
[ -n "$D" ] && echo " ⚠ XSS risk — use DOMPurify:" && echo "$D" || echo " ✓ No dangerouslySetInnerHTML"
|
|
333
|
+
local T=$(grep -rn "localStorage\|sessionStorage" app/ src/ --include="*.ts" --include="*.tsx" 2>/dev/null | grep -i "token\|jwt\|secret" | head -5)
|
|
334
|
+
[ -n "$T" ] && echo " ⚠ Tokens in storage — use httpOnly cookies:" && echo "$T" || echo " ✓ No tokens in storage"
|
|
335
|
+
curl -s "$PROD_URL/api/nonexistent" 2>/dev/null | grep -qi "stack\|Error:" && echo " ✗ Stack trace leak" || echo " ✓ No stack leak"
|
|
336
|
+
}
|
|
337
|
+
```
|
|
200
338
|
|
|
201
|
-
|
|
202
|
-
curl -sI "$PROD" | grep -i "http\|status"
|
|
339
|
+
---
|
|
203
340
|
|
|
204
|
-
|
|
205
|
-
curl -sI "$PROD/tools/keyword-density-checker" | grep "200\|301\|404"
|
|
341
|
+
## Pre-Commit Hook
|
|
206
342
|
|
|
207
|
-
|
|
208
|
-
|
|
343
|
+
```bash
|
|
344
|
+
cat > .git/hooks/pre-commit << 'EOF'
|
|
345
|
+
#!/bin/sh
|
|
346
|
+
npx tsc --noEmit || exit 1
|
|
347
|
+
npx eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0 || exit 1
|
|
348
|
+
EOF
|
|
349
|
+
chmod +x .git/hooks/pre-commit
|
|
350
|
+
```
|
|
209
351
|
|
|
210
|
-
|
|
211
|
-
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## CI/CD (GitHub Actions)
|
|
355
|
+
|
|
356
|
+
```yaml
|
|
357
|
+
name: QA
|
|
358
|
+
on: [push, pull_request]
|
|
359
|
+
jobs:
|
|
360
|
+
qa:
|
|
361
|
+
runs-on: ubuntu-latest
|
|
362
|
+
steps:
|
|
363
|
+
- uses: actions/checkout@v4
|
|
364
|
+
- uses: actions/setup-node@v4
|
|
365
|
+
- run: npm ci
|
|
366
|
+
- run: npx tsc --noEmit
|
|
367
|
+
- run: npx eslint . --ext .js,.jsx,.ts,.tsx --max-warnings 0
|
|
368
|
+
- run: npm test -- --runInBand --passWithNoTests
|
|
369
|
+
- run: npm run build
|
|
212
370
|
```
|
|
213
371
|
|
|
214
372
|
---
|
|
215
373
|
|
|
216
|
-
##
|
|
374
|
+
## Best Practices
|
|
375
|
+
|
|
376
|
+
| ✅ Do | ❌ Don't |
|
|
377
|
+
|-------|----------|
|
|
378
|
+
| Run full 13-phase flow before deploy | Skip typecheck or lint |
|
|
379
|
+
| Set `PROD_URL` in profile/.envrc | Hardcode URLs in scripts |
|
|
380
|
+
| OG images ≥ 1200×630 | Use small OG images |
|
|
381
|
+
| Animate with `transform`+`opacity` | Animate width/height/top |
|
|
382
|
+
| Show loading/error/empty states | Leave users on blank screens |
|
|
383
|
+
| `prefers-reduced-motion` for animations | Force motion on all users |
|
|
384
|
+
| HttpOnly + Secure cookies for tokens | localStorage for auth tokens |
|
|
385
|
+
| Error boundaries at all levels | White screen on crash |
|
|
386
|
+
| Database indexes + include/populate | N+1 queries in loops |
|
|
387
|
+
| `npm audit` before deploy | Deploy with known vulns |
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Common Pitfalls
|
|
392
|
+
|
|
393
|
+
| Problem | Solution |
|
|
394
|
+
|---------|----------|
|
|
395
|
+
| OG tags missing in raw HTML | Use `export const metadata` in Next.js |
|
|
396
|
+
| `Disallow: /` in robots.txt | Blocks all crawlers — use specific paths |
|
|
397
|
+
| Cards different heights in grid | Use `display: grid` with equal-height rows, not flex |
|
|
398
|
+
| Text overflows card | Add `text-overflow: ellipsis` + `overflow: hidden` |
|
|
399
|
+
| Animation jank | Animate `transform` not `width`/`height` |
|
|
400
|
+
| Form submits twice | Disable button on first click |
|
|
401
|
+
| Console errors in prod | Add `no-console` ESLint rule |
|
|
402
|
+
| DB connection timeout | Add connection pooling (PgBouncer/Prisma Accelerate) |
|
|
403
|
+
| Sensitive data in API | Strip `passwordHash`/`secret` in response transformer |
|
|
404
|
+
| App crashes on error | Add `app/error.tsx` error boundary |
|
|
405
|
+
| Large JS bundles | Dynamic import heavy components, analyze with `next/bundle-analyzer` |
|
|
406
|
+
| Images load slowly | Add `loading="lazy"`, use WebP/AVIF, resize to display size |
|
|
217
407
|
|
|
218
|
-
|
|
408
|
+
---
|
|
409
|
+
|
|
410
|
+
## Security Notes
|
|
219
411
|
|
|
220
|
-
-
|
|
221
|
-
-
|
|
222
|
-
-
|
|
223
|
-
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
- [ ] Important pages show `○` or `●` in build output (not `λ`)
|
|
227
|
-
- [ ] SEO tags visible in `curl` output for key pages
|
|
228
|
-
- [ ] All sitemap routes return valid XML
|
|
229
|
-
- [ ] No new 404s on previously working routes
|
|
230
|
-
- [ ] No secrets in git diff
|
|
231
|
-
- [ ] Commit message is scoped and descriptive
|
|
232
|
-
- [ ] Social preview platforms show correct card after cache refresh
|
|
412
|
+
- All `qa:*` functions are read-only (tsc, lint, test, build, curl, grep)
|
|
413
|
+
- `PROD_URL` and `QA_AUTH_HEADER` only for environments you own
|
|
414
|
+
- Basic secret scanning in `git diff` — for prod, use `trufflehog`/`git-secrets`
|
|
415
|
+
- Auth tests with real credentials against prod is destructive — use staging
|
|
416
|
+
|
|
417
|
+
---
|
|
233
418
|
|
|
234
419
|
## Limitations
|
|
235
420
|
|
|
236
|
-
- Passing
|
|
237
|
-
- Some checks depend on project-specific
|
|
238
|
-
- Manual
|
|
421
|
+
- Passing all phases reduces risk but doesn't eliminate production bugs
|
|
422
|
+
- Some checks depend on project-specific tooling (Prisma, NextAuth, etc.)
|
|
423
|
+
- Manual UX testing still required for critical user journeys
|
|
424
|
+
- SEO checks verify raw HTML only — not social preview rendering
|
|
425
|
+
- Route checks verify status codes, not content correctness
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## Master Checklist
|
|
430
|
+
|
|
431
|
+
### Phase 1: Code
|
|
432
|
+
- [ ] `tsc --noEmit`, `eslint`, `npm test` pass
|
|
433
|
+
|
|
434
|
+
### Phase 2: Build
|
|
435
|
+
- [ ] `npm run build` succeeds, no errors, pages static
|
|
436
|
+
|
|
437
|
+
### Phase 3: Auth
|
|
438
|
+
- [ ] Endpoints respond, protected routes denied, secure cookies
|
|
439
|
+
|
|
440
|
+
### Phase 4: Routes
|
|
441
|
+
- [ ] All core pages 200, sitemap valid, robots.txt correct
|
|
442
|
+
|
|
443
|
+
### Phase 5: SEO
|
|
444
|
+
- [ ] title, description, og:*, twitter:card, canonical, favicon, slugs
|
|
445
|
+
|
|
446
|
+
### Phase 6: API
|
|
447
|
+
- [ ] Status, Content-Type, consistent errors, timing
|
|
448
|
+
|
|
449
|
+
### Phase 7: Git
|
|
450
|
+
- [ ] No secrets, no artifacts, conventional commit
|
|
451
|
+
|
|
452
|
+
### Phase 8: Smoke
|
|
453
|
+
- [ ] Homepage + key pages 200, og:image loads
|
|
454
|
+
|
|
455
|
+
### Phase 9: Speed
|
|
456
|
+
- [ ] Lighthouse ≥ 90, lazy images, dynamic imports, font-display: swap
|
|
457
|
+
|
|
458
|
+
### Phase 10: Clean
|
|
459
|
+
- [ ] No vulns, no debug artifacts, unused deps pruned
|
|
460
|
+
|
|
461
|
+
### Phase 11: UI/UX
|
|
462
|
+
- [ ] Cards responsive, error boundaries, button states, reduced-motion
|
|
463
|
+
|
|
464
|
+
### Phase 12: Database
|
|
465
|
+
- [ ] Indexes, no N+1, no hardcoded URLs, no sensitive leaks
|
|
466
|
+
|
|
467
|
+
### Phase 13: Secure Rendering
|
|
468
|
+
- [ ] No secrets in client, no XSS, no stack leaks, UUIDs
|