Imported from sickn33/agentic-awesome-skills (
skills/vibecode-production-qa-validator/SKILL.md). Install upstream withnpx skills add sickn33/agentic-awesome-skills --skill vibecode-production-qa-validator. Copyright stays with the author.
Production QA Validator
Use the applicable phases in order and record evidence for each as passed, failed, incomplete or not applicable with a reason. Missing tooling, no tests, failed network calls and unperformed manual checks are incomplete, never success. Confirm project scripts, versions, approved URLs/methods, request limits, credentials and mutation boundaries before running. Builds/tests/lint/plugins can execute project code, write caches or reach services; they are not inherently read-only. Do not install hooks or overwrite existing config without authorization.
When to Use
- Use before shipping or promoting a fullstack Next.js app to production.
- Use after large UI, SEO, auth, API, database, or dependency changes need a concrete launch-readiness pass.
- Use when you need a compact command-driven checklist for build, route, metadata, performance, security, and cleanup checks.
export PROD_URL="https://yourdomain.com"
export QA_AUTH_HEADER="" # optional: "Bearer eyJ..."
export PAGESPEED_API_KEY="" # optional: for auto PageSpeed API
Evidence and a Bounded Route Check
The former consolidated qa:* runner returned successful exit codes after warnings, hid tool/network failures and inferred security from grep matches. It has been removed; a checklist is not an implemented automated gate. Use the project's actual checks and parse structured outputs. Keep raw logs private and redact secrets rather than echoing matched credential lines.
# Bash, approved staging target only; expect the exact documented status.
qa_route() {
local route="$1" expected="$2" code
code=$(curl --silent --show-error --max-time 15 --connect-timeout 5 \
--output /dev/null --write-out '%{http_code}' "$PROD_URL$route") || return 1
printf '%s %s\n' "$code" "$route"
[ "$code" = "$expected" ]
}
qa_route / 200
qa_route /api/protected 401 # choose401/403 from the actual contract
Do not follow redirects carrying credentials to other origins. A status check proves only that response, not content, authorization, availability, SEO or a complete workflow. Auth probes need real configured endpoints and correct methods; never call logout/login mutations indiscriminately in production. Validate object/tenant isolation with owned synthetic accounts and explicit negative cases.
Phase 1: Code Integrity
- The project's pinned typecheck script
- The project's pinned lint script (flags differ by ESLint version)
-
npm test # use the actual runner; zero discovered tests is incomplete
Phase 2: Build Verification
-
npm run buildsucceeds - Verify intended static/dynamic behavior; dynamic rendering is valid for many SEO pages
- Build log has no errors
| Symbol | Meaning |
|---|---|
○ |
Static |
● |
SSG |
λ |
Dynamic/serverless |
⊕ |
Partial prerender |
Phase 3: API Session & Authentication
- Auth endpoints respond (login, session, logout)
- Protected routes return 401/403
- Session cookie: HttpOnly + Secure + SameSite
- Cookie not expired, Path/Domain correct
- No rate limiting bypass
Phase 4: Route Regression
- Core pages, sitemap, robots.txt all 200
- URLs use kebab-case, no duplicate slugs
- robots.txt allows indexing
- Sitemap XML valid, all URLs resolve 200
Phase 5: SEO — Tags, Images, Favicon, Slugs
-
<title>30–60 chars, unique per page -
<meta name="description">in raw HTML - og:title matches
<title>, og:url matches canonical - og:image uses the target platform's supported dimensions/format, absolute URL, loads 200
- twitter:card = summary_large_image
- Canonical self-referencing, no duplicates
-
/favicon.ico200, apple-touch-icon present -
hreflangtags if multilingual - JSON-LD structured data present
- Slugs are stable/readable and preserve existing redirects; no arbitrary stop-word ban
Phase 6: API Route Behavior
- Correct status codes + Content-Type
- Errors return consistent JSON
{ error, message } - Response latency meets the measured route-specific SLO
- CORS headers correct (if cross-origin)
Phase 7: Git Hygiene
- No secrets/credentials in diff
- No
.next/node_modulesstaged - Commit:
type(scope): message
Phase 8: Post-Deployment Smoke Test
- Homepage 200, key pages 200
- OG image loads 200
- No console errors (manual)
- Auth flow works (manual)
Phase 9: Page Speed, Lazy Load & Bundles
- Lighthouse ≥ 90 (Perf, A11y, SEO)
- Record lab/field conditions; assess field LCP≤2.5s, INP≤200ms and CLS≤0.1 at the75th percentile
- Below-fold images may lazy-load; prioritize the LCP/above-fold image
- Dynamic imports for heavy components
- Largest JS chunk < 200KB gzipped
-
font-display: swap, no FOIT - Total page weight < 1MB
Phase 10: Cleanup & Vulnerability Scan
-
npm prune,depcheck— no unused deps - No console.log/debugger in staged code
-
npm audit— zero critical/high vulnerabilities - No eval/new Function/document.write
- TODOs resolved
Phase 11: UI/UX — Cards, Animation, Error Boundaries
- Cards: equal height grid, no overlap, text ellipsis, responsive (1→2→3 col)
- No horizontal scroll at any viewport (320–1440px)
- Images: consistent
aspect-ratio+object-fit: cover - Touch targets ≥ 44×44px
- Animations use
transform+opacityonly (not layout props) -
prefers-reduced-motionrespected - Error boundaries at root + route level (
app/error.tsx,app/global-error.tsx) -
app/not-found.tsxandapp/loading.tsxexist - All client fetches show loading + error + empty states
- Buttons: hover, focus-visible, active, disabled, loading states
- Forms prevent repeat submissions and server writes enforce atomic idempotency where needed
Phase 12: Database & Data Layer
- Connection pool configured (no starvation)
- Schema in sync with migrations
- Indexes and batching justified by actual query plans/workload; measure N+1
- No hardcoded DB credentials in source
- No raw SQL injection risk
- No sensitive data leaked in API responses
- Migrations are idempotent
Phase 13: Secure Data Rendering
- No secrets/tokens in client source or localStorage
- Use framework escaping or context-appropriate sanitization for untrusted HTML; sanitization is not a universal safe sink
- API errors don't leak stack traces
- Enforce object/tenant authorization regardless of identifier format; UUIDs are not access control
- User emails masked in UI
- NEXT_PUBLIC_ vars contain no secrets
Pre-Commit Hook
Use the project's existing hook manager and preserve installed hooks. Configure only after authorization; local hooks can be bypassed and do not replace CI.
CI/CD (GitHub Actions)
Template only: select pinned compatible tools/actions, the actual test runner and explicit permissions. Do not enable production probes or pass secrets to untrusted PR code.
name: QA
on: [push, pull_request]
jobs:
qa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- run: npx tsc --noEmit
- run: npm run lint
- run: npm test # configure zero-test discovery to fail
- run: npm run build
Best Practices
| ✅ Do | ❌ Don't |
|---|---|
| Run full 13-phase flow before deploy | Skip typecheck or lint |
Set PROD_URL in profile/.envrc |
Hardcode URLs in scripts |
| OG images ≥ 1200×630 | Use small OG images |
Animate with transform+opacity |
Animate width/height/top |
| Show loading/error/empty states | Leave users on blank screens |
prefers-reduced-motion for animations |
Force motion on all users |
| HttpOnly + Secure cookies for tokens | localStorage for auth tokens |
| Error boundaries at all levels | White screen on crash |
| Database indexes + include/populate | N+1 queries in loops |
npm audit before deploy |
Deploy with known vulns |
Common Pitfalls
| Problem | Solution |
|---|---|
| OG tags missing in raw HTML | Use export const metadata in Next.js |
Disallow: / in robots.txt |
Blocks all crawlers — use specific paths |
| Cards different heights in grid | Use display: grid with equal-height rows, not flex |
| Text overflows card | Add text-overflow: ellipsis + overflow: hidden |
| Animation jank | Animate transform not width/height |
| Form submits twice | Disable button on first click |
| Console errors in prod | Add no-console ESLint rule |
| DB connection timeout | Add connection pooling (PgBouncer/Prisma Accelerate) |
| Sensitive data in API | Strip passwordHash/secret in response transformer |
| App crashes on error | Add app/error.tsx error boundary |
| Large JS bundles | Dynamic import heavy components, analyze with next/bundle-analyzer |
| Images load slowly | Measure the image; eagerly load/priority the LCP image, lazy-load appropriate below-fold assets |
Security Notes
- Project commands can mutate state or execute arbitrary lifecycle/tool code; inspect them and use an isolated approved environment.
PROD_URLandQA_AUTH_HEADERonly for environments you own- Use a reviewed secret scanner with redacted output; missing matches do not prove absence. Validate dependencies from structured audit results and propagate command failures.
- Auth tests with real credentials against prod is destructive — use staging
Limitations
- Passing all phases reduces risk but doesn't eliminate production bugs
- Some checks depend on project-specific tooling (Prisma, NextAuth, etc.)
- Manual UX testing still required for critical user journeys
- SEO checks verify raw HTML only — not social preview rendering
- Route checks verify status codes, not content correctness
Master Checklist
Phase 1: Code
-
tsc --noEmit,eslint,npm testpass
Phase 2: Build
-
npm run buildsucceeds, no errors, pages static
Phase 3: Auth
- Endpoints respond, protected routes denied, secure cookies
Phase 4: Routes
- All core pages 200, sitemap valid, robots.txt correct
Phase 5: SEO
- title, description, og:*, twitter:card, canonical, favicon, slugs
Phase 6: API
- Status, Content-Type, consistent errors, timing
Phase 7: Git
- No secrets, no artifacts, conventional commit
Phase 8: Smoke
- Homepage + key pages 200, og:image loads
Phase 9: Speed
- Lighthouse ≥ 90, lazy images, dynamic imports, font-display: swap
Phase 10: Clean
- No vulns, no debug artifacts, unused deps pruned
Phase 11: UI/UX
- Cards responsive, error boundaries, button states, reduced-motion
Phase 12: Database
- Indexes, no N+1, no hardcoded URLs, no sensitive leaks
Phase 13: Secure Rendering
- No secrets in client, no XSS, no stack leaks, UUIDs
