debug-perf
Diagnose and fix Next.js development and production performance problems. Use when investigating hot-reload loops, CPU spikes, bundle bloat, or slow server work.
- Category
- devops
- Package
- debug-perf/SKILL.md
- License
- MIT
- Author
- @tushaarmehtaa
- Tags
- performancenextjsturbopackwebpackbundlecachingcpu
Install
Swipe for more runtimes.
Codex
Skills directory: ~/.codex/skills
Install globally
npx skills add tushaarmehtaa/tushar-skills --skill debug-perf -g -a codex -yInvoke
$debug-perf or /skillsYou can also describe the task naturally; runtimes may select the skill from its description.
Required access
Claude Code
Skills directory: ~/.claude/skills
Install globally
npx skills add tushaarmehtaa/tushar-skills --skill debug-perf -g -a claude-code -yInvoke
/debug-perfYou can also describe the task naturally; runtimes may select the skill from its description.
Required access
Cursor
Skills directory: ~/.cursor/skills
Install globally
npx skills add tushaarmehtaa/tushar-skills --skill debug-perf -g -a cursor -yInvoke
/debug-perfYou can also describe the task naturally; runtimes may select the skill from its description.
Required access
local coding agent required
This skill requires project files and terminal commands. Uploading it to a chat app does not provide equivalent execution.
ChatGPT Skills
This workflow needs a local coding environment or capabilities that a chat-only Skills upload does not provide.
Why local agent required →Instructions
Source: SKILL.mdDiagnose slow or overheating Next.js apps. Works in dev and production.
Steps
1. Check for compile loops
ls -lh /tmp/*.log 2>/dev/null
# If any log is >100MB, a hot reload loop is running
Look for repeated module resolution errors in the dev server output. Common culprit: geist/font/* imports breaking with Turbopack. Fix by switching to next/font/google:
// layout.tsx — replace geist package imports
import { Geist, Geist_Mono } from "next/font/google";
const GeistSans = Geist({ subsets: ["latin"], variable: "--font-geist-sans" });
const GeistMono = Geist_Mono({ subsets: ["latin"], variable: "--font-geist-mono" });
2. Check file watching scope
If the project reads files outside its own directory at runtime:
// lib/something.ts
const ROOT = path.join(process.cwd(), ".."); // watches the parent dir
Turbopack watches any directory referenced by runtime file reads. Edits to files in .. trigger full recompiles. Fix: scope reads to the project directory, or use turbopack: {} in next.config.ts to silence the warning while you plan a proper fix.
3. Check for uncached disk reads
grep -rn "fs.readFileSync\|fs.readdirSync" lib/ app/ src/ 2>/dev/null
Any function that reads files and is called from a server component runs on every request. Add a module-level cache:
let cache: ReturnType<typeof loadData> | null = null;
export function loadData() {
if (cache) return cache;
// ... read files ...
cache = result;
return cache;
}
4. Profile the bundle (production)
npx @next/bundle-analyzer
# or add to next.config.ts:
# bundleAnalyzer: { enabled: process.env.ANALYZE === 'true' }
Look for: large client components that could be server components, duplicate packages across chunks, packages that shouldn't be in the client bundle.
5. Find expensive server components
Server components re-render on every request in dev unless wrapped with cache(). Search for:
grep -rn "await fetch\|readFileSync\|prisma\.\|supabase\." app/ --include="*.tsx" --include="*.ts"
Any expensive call in a server component without import { cache } from 'react' wrapping it will run on every page load.
6. Report
State:
- Root cause (loop, file watching, uncached reads, bundle)
- Files changed and what changed
- Expected behavior after fix (idle CPU, hot reload time)