# Debug Frontend

> Systematic 5-step debugging flow for Next.js 15 + React 19 + TypeScript apps. Load when a UI bug is reported, hydration error appears, Server Action returns wrong data, or cache invalidation fails. Forces layer isolation (server vs client, action vs component, cache vs render) before touching code — prevents "fix here, break there" cascades.

- **Type:** Skill
- **Install:** `agentstack add skill-yerdaulet-damir-vibe-coding-rules-debug-frontend`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [yerdaulet-damir](https://agentstack.voostack.com/s/yerdaulet-damir)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [yerdaulet-damir](https://github.com/yerdaulet-damir)
- **Source:** https://github.com/yerdaulet-damir/vibe-coding-rules/tree/main/.claude/skills/debug-frontend
- **Website:** https://vibecodex-omega.vercel.app

## Install

```sh
agentstack add skill-yerdaulet-damir-vibe-coding-rules-debug-frontend
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# debug-frontend

Stop. Do not edit any file yet. Work through these 5 steps in order.

---

## Step 1 — Locate the layer

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//components/` |
| Hydration mismatch | Server vs client divergence | `grep -rn "Date()\|Math.random\|window\." src/features//` |
| Wrong data after mutation | Cache invalidation | `grep -rn "revalidateTag\|revalidatePath" src/features//actions.ts` |
| Server Action returns `{ error: ... }` unexpectedly | Validation or repo | `grep -n "safeParse\|throw" src/features//actions.ts` |
| Type error / weird `undefined` | Schema / types | `grep -rn "z\.infer\|as any\|@ts-ignore" src/features//` |
| Slow page / waterfall | Data fetch shape | `grep -n "await " src/app//page.tsx` (count sequential awaits) |

Pick **one** layer. Do not touch any other layer in this debug pass.

---

## Step 2 — Check the 5 most common Next.js antipatterns

These cause the majority of vibe-coded bugs. Grep for each:

```bash
# 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 |

---

## Step 3 — Reproduce the bug deterministically

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 'alice@x.com'
3. Submit form with empty name
4. EXPECTED: error shown next to Name field
5. ACTUAL: page reloads with stale data
```

**For a Server Action bug:** call the action in isolation:
```typescript
// 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:
```bash
# 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.ts
```

If the read uses `tags.user(id)` but the write only invalidates `tags.userList()` — there's your bug.

---

## Step 4 — Fix in the correct layer

Minimum change. Do not refactor unrelated code.

| Layer | Where to fix |
|-------|------------|
| Server Component bug | `src/features//components/Page.tsx` |
| Client Component bug | `src/features//components/.tsx` |
| Mutation bug | `src/features//actions.ts` |
| Validation bug | `src/features//schema.ts` |
| Data access bug | `src/features//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.

---

## Step 5 — Verify

```bash
# 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.

---

## Common error → root cause table

| 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 `await`s 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 |

---

## Verification

The skill was applied correctly when:
- [ ] A reproducible scenario exists (Step 3)
- [ ] Fix touches exactly one layer
- [ ] All 5 antipattern greps still come up clean
- [ ] `pnpm typecheck && pnpm lint` exits 0
- [ ] The reproduction scenario now passes

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [yerdaulet-damir](https://github.com/yerdaulet-damir)
- **Source:** [yerdaulet-damir/vibe-coding-rules](https://github.com/yerdaulet-damir/vibe-coding-rules)
- **License:** MIT
- **Homepage:** https://vibecodex-omega.vercel.app

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-yerdaulet-damir-vibe-coding-rules-debug-frontend
- Seller: https://agentstack.voostack.com/s/yerdaulet-damir
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
