Frontend web
Use when writing, refactoring, or debugging React/Next.js frontend code (App Router, Server/Client Components, hooks, Tailwind/CSS Modules) — before adding a component, choosing where state lives, wiring data fetching, or preparing a production deploy; or when facing hydration mismatch, NEXT_PUBLIC_ env leaks, excessive re-render, bundle size bloat, CLS, SEO/metadata gaps, or XSS via dangerouslySetInnerHTML.From its SKILL.md
npx -y skills add tienenwu/fables --skill frontend-webAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
6.1 KB, ~1.3k tokens by cl100k_base, as published. Nobody here has run it
🌐 繁體中文(canonical) · English mirror
React / Next.js Frontend Judgment Handbook
Core Principles
- A green dev server proves nothing: hydration, env-var injection, bundle size, SEO metadata, and minification only show their true behavior under
next build && next start— any change on the production path must be verified with a production build. - Remote data and UI state are two different things: server state (from an API/DB — it goes stale, needs caching, needs refetching) belongs to React Query/SWR; client state (pure view toggles, input fields) uses useState/zustand. Mixing the two is the root of most "data out of sync" bugs.
- Put state at the lowest layer that uses it: default to local, lift only when it hurts, go global last. Reaching for a global store too early is entropy, not architecture.
- A re-render is a symptom, not the disease: first use the Profiler to measure which component re-renders and why, then decide whether to memo; scattering useMemo/useCallback on gut feel is just noise.
- Anything that enters the client bundle is visible to the user:
NEXT_PUBLIC_-prefixed variables, strings hardcoded into components, whole libraries imported into a Client Component — assume it is public first, then prove it deserves to be public.
Task Triage
| Situation | Path | Read first |
|---|---|---|
| New screen/feature | First decide where data comes from, who owns state, what needs "use client", then write the UI | references/architecture-state.md |
| Write/change a component, extract a component, styling | First settle the semantic boundary and props contract, then act | references/components-styling.md |
| Janky screen, too many re-renders, oversized bundle | Do not scatter memo first — measure first | references/rendering-performance.md |
| Fetch remote data, caching, loading/error states | Separate server state from client state | references/architecture-state.md §1 |
| Ship to production / deploy / diagnose "fine in dev, blows up in prod" | Run the mandatory checklist line by line | references/release-checklist.md |
| hydration mismatch, env vars, SEO | Assume a build-time difference first, do not thrash | references/release-checklist.md |
Red Lines (Absolutely Forbidden)
- Never declare a release-relevant change done after verifying only on the dev server — hydration,
NEXT_PUBLIC_injection, bundle, minify, and metadata are all misrepresented in dev. - Never prefix a secret (API key, DB connection string, private key) with
NEXT_PUBLIC_or hardcode it into a Client Component — it gets bundled into the JS, readable by any user, equivalent to publishing the secret. - Never feed
dangerouslySetInnerHTMLa user-controllable string without sanitizing — that is direct XSS; a user's<script>will execute in someone else's browser. - Never use an array index as the
keyof a list that will be inserted into / removed from / reordered — on insert or sort React mismatches the DOM, so input-field contents jump to the wrong row and checkbox states end up on the wrong item. - Never read
window/localStorage/Date.now()/Math.random()directly during render to decide output — the server has no such value or a different one, causing a hydration mismatch that makes the whole tree get thrown away and re-rendered on the client. - Never loosen tests/type checks to turn CI green — two red runs in a row is a wrong-direction signal; back up to the previous decision point, do not comment out the assertion.
Failure Signals (Back Up, Don't Retry)
| Symptom | Usually means | Back up to |
|---|---|---|
| It took a pile of useMemo/useCallback to stop the jank | Upstream passes unstable props, or state sits too high | Use the Profiler to find the real re-render source, re-examine the state layer |
Every component needs a useEffect to sync its own copy of the data | Server state got stuffed into useState | Switch to React Query/SWR as the single source of truth |
More and more suppressHydrationWarning being added | Server/client output is fundamentally inconsistent | Find the divergent value (Date/random/browser API) and move it into useEffect |
| Props drilled down 5 levels (prop drilling) | State should be lifted or moved to context/store | Re-examine who owns the state, don't keep drilling |
Every change requires adding 'use client' one layer higher to stop the error | The client boundary is drawn wrong, dragging Server Component content down with it | Re-examine the boundary: only interactive leaf nodes need client |
| The same hydration error survives three rewrites | You are guessing without locating the divergent value | Read the component named in the console, diff server vs client HTML |
References Index
references/architecture-state.md— server vs client state boundary, which layer state lives in, Server/Client Component decisions, where data fetching happens. Read before touching architecture or a new feature.references/components-styling.md— when to extract a component, props contracts, controlled vs uncontrolled, CSS strategy, a11y red lines. Read before writing UI.references/rendering-performance.md— measure first, memo criteria, list keys, code splitting, images/fonts/CLS. Read when janky or the bundle is too large.references/release-checklist.md— env-var leaks, hydration diagnosis, SEO, real production-build testing, XSS, error boundaries, bundle thresholds. Tick off line by line before publishing.references/test-scenarios.md— the judgment test set, to verify an inheriting model follows the rules. Do not let a running model read it.
What ships with it: 5 files
32.8 KB alongside SKILL.md
references/
- architecture-state.md6.9 KB
- components-styling.md6.7 KB
- release-checklist.md7.4 KB
- rendering-performance.md6.4 KB
- test-scenarios.md5.4 KB