debug-frontend — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited debug-frontend (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Stop. Do not edit any file yet. Work through these 5 steps in order.
Next.js bugs almost always live in one of 5 layers. Identify which one before touching code.
| Symptom | Likely layer | First grep | ||
|---|---|---|---|---|
| 500 / runtime error in browser | Client component | grep -rn "'use client'" src/features/<domain>/components/ | ||
| Hydration mismatch | Server vs client divergence | `grep -rn "Date()\ | Math.random\ | window\." src/features/<domain>/` |
| Wrong data after mutation | Cache invalidation | `grep -rn "revalidateTag\ | revalidatePath" src/features/<domain>/actions.ts` | |
Server Action returns { error: ... } unexpectedly | Validation or repo | `grep -n "safeParse\ | throw" src/features/<domain>/actions.ts` | |
Type error / weird undefined | Schema / types | `grep -rn "z\.infer\ | as any\ | @ts-ignore" src/features/<domain>/` |
| Slow page / waterfall | Data fetch shape | grep -n "await " src/app/<route>/page.tsx (count sequential awaits) |
Pick one layer. Do not touch any other layer in this debug pass.
These cause the majority of vibe-coded bugs. Grep for each:
# Antipattern 1: 'use client' on a page or layout (forces 100% client tree)
grep -rn "'use client'" src/app/ | grep -E "(page|layout)\.tsx"
# Antipattern 2: useEffect for data fetching (race conditions, no Suspense)
grep -rn "useEffect.*fetch\|useEffect.*async" src/features/
# Antipattern 3: revalidateTag with magic string (typo = silent miss)
grep -rn "revalidateTag(['\"]" src/ # should find nothing — all should use tags.X()
# Antipattern 4: throw for business errors (breaks errors-as-values)
grep -rn "throw new Error" src/features/*/actions.ts
# Antipattern 5: drizzle-orm leaked outside repository.ts
grep -rn "from 'drizzle-orm" src/features/*/components/ src/features/*/actions.ts| Result | Root cause | Principle |
|---|---|---|
'use client' on page/layout | Whole tree client-rendered, no RSC benefits | C4 |
useEffect + fetch | Race conditions, waterfall, hydration mismatch | C9 / D2 |
Magic-string revalidateTag | Cache miss in production due to typo | D1 |
throw in Server Action | Client gets generic error, can't show field hint | C5 |
drizzle-orm in component | Hexagonal boundary broken | B1 / D6 |
Before changing code, prove you can trigger it on demand.
For a UI bug: narrow the user flow:
1. Visit /users
2. Click "Edit" on user '[email protected]'
3. Submit form with empty name
4. EXPECTED: error shown next to Name field
5. ACTUAL: page reloads with stale dataFor a Server Action bug: call the action in isolation:
// scratch test
const result = await createUser({ email: '', name: '' });
console.log(result); // expected: { success: false, error: 'Invalid input' }For a cache invalidation bug: check both sides:
# 1. Is the read tagged?
grep -A2 "fetch.*users" src/features/users/ # look for next: { tags: [...] }
# 2. Is the write invalidating the same tag?
grep -A3 "revalidateTag" src/features/users/actions.tsIf the read uses tags.user(id) but the write only invalidates tags.userList() — there's your bug.
Minimum change. Do not refactor unrelated code.
| Layer | Where to fix |
|---|---|
| Server Component bug | src/features/<domain>/components/<Feature>Page.tsx |
| Client Component bug | src/features/<domain>/components/<Leaf>.tsx |
| Mutation bug | src/features/<domain>/actions.ts |
| Validation bug | src/features/<domain>/schema.ts |
| Data access bug | src/features/<domain>/repository.ts |
| Cache miss | src/lib/cache/tags.ts + relevant action |
Hydration mismatches specifically: add suppressHydrationWarning only as a last resort — first try moving the non-deterministic code (Date, random, window) to a client useEffect for initial render or to a server-only computation.
# Type check
pnpm typecheck
# Lint
pnpm lint
# Run the failing scenario again — must succeed now
pnpm dev
# (manually walk through the reproduction steps from Step 3)Then run the antipattern greps from Step 2 again. You must not have introduced any new violation while fixing.
| Error / Symptom | Where to look first | Likely cause |
|---|---|---|
Hydration failed because the initial UI does not match | Client component | Date() or Math.random() in render |
useActionState is undefined | Imports | Missing 'use client' directive |
| Form submits but data doesn't refresh | Server Action | Missing revalidateTag or wrong tag |
Cannot read properties of undefined (reading 'X') after fetch | Schema | API response doesn't match Zod schema; safeParse returned error and was ignored |
| 500 on Server Action | actions.ts | throw for a business error instead of returning { success: false } |
| Page is slow but data loads fast in isolation | Page structure | Sequential awaits creating waterfall (Principle D3) |
Shows stale data after router.refresh() | Cache | Tag mismatch between fetch and invalidate |
dynamic = 'force-dynamic' but PPR enabled warning | next.config | Either remove force-dynamic or remove PPR for that route |
| Bundle size grew | Component tree | 'use client' on a page pulled the whole tree client-side |
The skill was applied correctly when:
pnpm typecheck && pnpm lint exits 0~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.