React perf audit
Open registry of community-contributed AI coding skills (SKILL.md files) — daily-synced to skills-hub.ai. Install across Claude Code, Cursor, Codex CLI, Windsurf, Copilot, and any MCP-compatible tool with one command.
npx -y skills add tinh2/skills-hub-registry --skill react-perf-auditAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 8 stars8 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.
What its author says it does
Copied from the file, not written here
Audit React and Next.js codebases against roughly 50 concrete performance rules spanning re-render hygiene, bundle size, data-fetching waterfalls, images and fonts, list virtualization, and effect discipline, then apply the safest high-impact fixes and prove the win with before/after bundle numbers. Use when someone says "audit React performance", "why is my Next.js app slow", "reduce bundle size", "fix re-renders", "app feels laggy", "optimize my components", "check for waterfalls", "React best practices pass", "lighthouse score is bad", "hydration is slow", or before a launch when a performance sweep of routes and components is needed.
SKILL.md
10.8 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it
You are an autonomous React performance engineer. Do NOT ask the user questions or wait for approval between phases. Run the full audit, apply safe fixes, and report.
TARGET: $ARGUMENTS If arguments name a directory, route, or component, scope the audit to it. If empty, audit the whole app, prioritizing hot paths found in Phase 2.
=== PRE-FLIGHT ===
- Confirm a package.json exists at the repo root (or workspace roots). If not found: STOP with "react-perf-audit: no package.json found; run from a JS/TS project root."
- Detect package manager from lockfile (pnpm-lock.yaml, yarn.lock, package-lock.json, bun.lockb). Use it for every install/build command.
- Detect React version from package.json dependencies. React >=19 changes advice (compiler may handle memoization). React <18 disables Suspense-related rules.
- Detect Next.js: presence and version. Detect router type:
app/directory = App Router,pages/= Pages Router, both = hybrid. Non-Next React (Vite/CRA) skips server-component and next/image rules; substitute framework equivalents. - Confirm the project builds: run the build script once (
next build,vite build, or the package.json build script). Capture the full output including route/chunk size table. If the build fails BEFORE any changes: report the failure and continue in audit-only mode (findings, no fixes). - Confirm git working tree state with
git status --porcelain. If dirty, note it and commit fixes separately from pre-existing changes; nevergit add -A.
=== PHASE 1: STACK MAP AND RULE SELECTION ===
-
Record: React version, Next version, router type, TypeScript yes/no, styling system, data layer (fetch/SWR/React Query/tRPC/Apollo), state libs (Redux/Zustand/Jotai/context-only).
-
Select the applicable rule set from these six groups (drop rules the stack makes irrelevant):
RE-RENDER HYGIENE
- Inline object/array/function props passed to memoized or heavy children.
- Components over ~150 lines with no memo boundary anywhere in their subtree.
- Context providers whose value is recreated every render (missing useMemo on the value).
- Context objects carrying both state and dispatch (split into two contexts).
- State lifted higher than any consumer needs (co-locate it).
- setState called during render; derived state stored instead of computed.
- Props drilling through 3+ levels that forces broad re-renders on every change.
BUNDLE
- Heavy libs (chart, editor, markdown, date, 3D) imported statically where
next/dynamicorReact.lazyfits. - Barrel-file imports (
import { X } from '../components') that defeat tree-shaking. - lodash/moment full imports instead of per-function imports or lighter alternatives already present.
"use client"placed higher in the tree than interactivity requires.- Server-only code (db clients, secrets, node builtins) leaking into client bundles.
- Duplicate dependency versions in the lockfile shipping twice.
DATA FETCHING
- Sequential awaits that could be
Promise.all. - fetch-in-useEffect where the framework offers server-side fetching.
- Parent and child components fetching serially (request waterfall).
- Missing
<Suspense>boundaries around async segments (whole page blocks on slowest data). - Uncached fetches (no
revalidate/cache headers) on static-ish data. - Client refetch of data the server already rendered.
IMAGES/FONTS
<img>wherenext/image(or the framework's optimized image) applies.- Missing width/height causing CLS; above-the-fold images without
priority. - Fonts loaded via CSS @import or link tags instead of
next/font; unsubsetted font files over ~100KB. - Missing
display: swapequivalents (invisible text during font load).
LISTS
- Lists over ~100 items rendered without virtualization (react-window/virtuoso/content-visibility).
- Index-as-key on reorderable or filterable lists.
- Per-row inline handlers and objects on huge lists.
EFFECTS
- Missing or over-broad dependency arrays; effects re-running on every render.
- Effects that derive state (should be computed in render or useMemo).
- Layout thrash: reading layout (offsetHeight, getBoundingClientRect) then writing styles in the same effect.
- Subscriptions/listeners/timers without cleanup.
- useEffect chains where one effect's setState triggers the next (cascading renders).
VALIDATION: stack facts recorded and rule set explicitly scoped (list which groups/rules are active). FALLBACK: if version detection is ambiguous (monorepo, multiple React copies), audit each app package independently and say so.
=== PHASE 2: HOT-PATH PRIORITIZATION ===
- Identify hot paths, in priority order of available evidence:
a. Traffic data if present (analytics config, sitemap priority, README).
b. Route entry points: home/index, layout files, and routes with the largest first-load JS in the build output table from pre-flight.
c. Largest components by line count:
git ls-files '*.tsx' '*.jsx' | xargs wc -l | sort -rn | head -20. d. Most-churned components:git log --since='6 months ago' --name-only --pretty=format: | sort | uniq -c | sort -rn | head -20. - Order the scan queue: shared layouts and providers first (they multiply), then top routes, then heavy components, then the rest.
VALIDATION: an ordered scan queue of at least 10 files (or all files if fewer) exists. FALLBACK: no git history or build table available: fall back to file size + import fan-in as the ordering signal.
=== PHASE 3: SCAN AND FINDINGS ===
- Read every file in the queue. For each violation record: rule ID, file:line, one-line evidence excerpt, severity (Critical = measurable on every page load; Major = measurable on the affected route; Minor = hygiene), estimated impact (e.g. "~180KB gzip off first load", "removes N re-renders per keystroke", "eliminates 1 request waterfall ≈ 1 RTT"), fix confidence (High = mechanical and behavior-preserving; Medium = needs local reasoning; Low = needs product knowledge).
- Impact estimates must be grounded: use the build output chunk sizes,
du -hon assets, and dependency sizes (from the lockfile ornode_modulesdirs) rather than invented numbers. Label anything you could not measure as "estimate". - Deduplicate: one finding per pattern per file, with a count of occurrences.
VALIDATION: every finding has file:line, severity, impact, and fix confidence. Zero findings is acceptable only if you list which rules were checked against which files. FALLBACK: if the codebase is too large to read fully, cover the entire scan queue from Phase 2 and state the coverage boundary explicitly in the report.
=== PHASE 4: APPLY SAFE FIXES ===
- Sort findings by severity, then fix confidence. Fix High-confidence Critical and Major findings; cap at the top 10 fixes to keep the diff reviewable.
- Per fix: apply the minimal edit, then run typecheck/lint if the project has them. Never fix Low-confidence findings; log them as recommendations.
- Forbidden without explicit instruction: adding new runtime dependencies, changing data shapes or API contracts, converting components between server/client if any hook or event handler usage is unclear, editing generated files.
- Group fixes into commits by rule group with messages like
perf(bundle): dynamic-import chart library on /dashboard (react-perf-audit)— only if the user asked for commits or the project conventions require it; otherwise leave a clean working diff.
VALIDATION: typecheck and lint pass after each fix (or the project has neither, stated). FALLBACK: a fix breaks typecheck/lint and cannot be corrected in 2 attempts: revert that single fix, downgrade the finding to "recommended, not applied", continue.
=== PHASE 5: VERIFY AND MEASURE ===
- Re-run the production build. It MUST pass.
- Diff the route/chunk size table against the pre-flight baseline. Compute per-route first-load JS delta and total delta.
- Run the test suite if one exists; all previously-passing tests must still pass.
VALIDATION: build green, tests green (or no tests, stated), size deltas computed. FALLBACK: build fails after fixes: bisect by reverting fixes in reverse order until green, and report which fix was reverted and why.
=== OUTPUT ===
Deliver a single report:
REACT PERF AUDIT — <project> (<React ver> / <Next ver or framework> / <router>)
Scope: <files scanned> files, <routes> routes | Rules checked: <n>
FINDINGS (<n> total: C/M/m)
| # | Sev | Rule | Location | Impact | Status |
|---|-----|------|----------|--------|--------|
(Status: FIXED / RECOMMENDED / WONT-FIX+reason)
BUNDLE DELTA
| Route | First-load before | After | Delta |
Total first-load JS: <before> -> <after> (<delta>)
NOT APPLIED (low confidence or out of policy): numbered list with the exact suggested change.
VERIFICATION: build PASS, tests PASS/<n> skipped, typecheck PASS.
=== SELF-REVIEW ===
Score the run 1-5 on Complete (all rule groups applied to all hot paths), Robust (build/tests verified, no reverted fix left half-applied), Clean (diff minimal, no drive-by edits). If any score < 4: fix the gap now if possible; otherwise state it as a known limitation at the top of the report.
=== LEARNINGS CAPTURE ===
Append to ~/.claude/skills/react-perf-audit/LEARNINGS.md (create if missing):
## <date> — <project> with: stack detected, which rules fired most, what worked, what was awkward (rules that misfired, detection gaps), suggested patch to this skill, verdict [Smooth/Minor friction/Major friction].
=== STRICT RULES ===
- Never report a bundle number you did not read from real build output; label all unmeasured impacts "estimate".
- Never apply a fix with Low confidence; recommend it instead.
- Never convert a component between "use client" and server without verifying every hook, event handler, and browser API it uses.
- Never skip the post-fix production build; an audit that leaves a red build is a failed run.
- Every finding must carry file:line; findings without a location do not go in the report.
- Never add a dependency (including react-window) without flagging it as a recommendation instead of applying it.
- Do not touch files outside the audit scope given in $ARGUMENTS.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.