.codex/skills/profile-browsing/SKILL.md
Profile app performance while browsing, collecting Web Vitals and React rerender data via react-scan. Orchestrates parallel profiler subagents via playwright-cli to capture navigation timing, long tasks, layout shifts, LCP, React commit counts, render bursts, and per-component render data. Use when profiling browsing performance, finding bottlenecks, diagnosing excessive rerenders, or auditing page performance.
npx skillsauth add bitsocialnet/5chan profile-browsingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Two-layer profiling: browser-level symptoms (Web Vitals, long tasks, scroll jank) and React-level diagnosis (commit counts, render bursts, per-component render data from react-scan). Each profiler subagent runs in its own browser session and context window.
yarn start via Portless)playwright-cli installed (npm install -g @playwright/cli@latest)IMPORTANT: The orchestrator (you) is responsible for ensuring exactly ONE dev server is running. Profiler subagents must NEVER start a dev server themselves.
The app has react-scan set up in src/lib/react-scan.ts with report: true. In dev mode it:
window.__getReactScanReport() for programmatic collectionThe profiler's addInitScript sets window.__PROFILING__ = true before the app loads, which tells react-scan to disable its toolbar and sounds during automated runs.
No additional setup needed — react-scan is already a devDependency and imported in the entry file.
Before spawning any profiler subagents, verify exactly one dev server is available:
# Check if the dev server is reachable
curl -sf http://5chan.localhost:1355 -o /dev/null && echo "OK" || echo "NOT RUNNING"
yarn start (backgrounded), then poll until it responds. Do NOT start more than one.ps aux | grep vite), reuse it — do not start another.Split routes into batches of 2–4 for parallel profiling.
Default batches (adjust boards as needed):
| Batch | Session | Routes | Focus |
|-------|---------|--------|-------|
| 1 | prof-1 | /all, /all/catalog | Multi-board feed + catalog |
| 2 | prof-2 | /biz, /biz/catalog | Single board feed + catalog |
| 3 | prof-3 | /pol, /pol/catalog, /g, /g/catalog | Board switching (feed reloads) |
Keep batches balanced. Add thread views (/:boardIdentifier/thread/:cid) as needed.
Read the profiler subagent definition at .codex/agents/profiler.toml. Then spawn one profiler subagent per batch in parallel using Codex's current delegation tool:
For each batch, create a subagent request that includes:
agent: "profiler"
Session name: "prof-N"
Routes to profile: /route1, /route2, ...
Any non-default app URL or extra profiling constraints
Spawn up to 4 subagents simultaneously. Each opens its own browser session, navigates routes, scrolls, collects both Web Vitals and react-scan data per route, and returns a structured issues list.
Trade-off: Parallel is faster but may skew timing results under heavy machine load. For precise measurements, spawn sequentially.
Collect structured output from each subagent and merge:
## Performance Profile Results
### Critical
- [metric]: [value] at [route] — [what likely needs fixing]
### Warning
- [metric]: [value] at [route] — [what likely needs fixing]
### React Rerenders
- [route]: [N] commits during load, [M] during scroll — [likely cause]
- Render bursts detected at [routes] — suggests cascading state updates
- Top rerendering components (react-scan):
- [ComponentName]: [total count] renders across [routes], [time]ms total
- [ComponentName]: [total count] renders across [routes], [time]ms total
### Scroll Jank
- [route]: [N] long tasks during scroll (max [X]ms), [M] React commits — [likely cause]
### Info
- [observations]
### Per-View Summary
| View | Nav (ms) | Long Tasks | CLS | LCP (ms) | Commits | Scroll Commits | Bursts | Top Component |
|------|----------|-----------|-----|-----------|---------|----------------|--------|---------------|
| /all | ... | ... | ... | ... | ... | ... | ... | ... |
| Signal | Likely cause | Fix direction |
|--------|-------------|---------------|
| High commits, no long tasks | Frequent cheap rerenders | React.memo, stabilize props |
| High commits + long tasks | Expensive rerenders | Profile render cost, split components |
| High scroll commits | Scroll/intersection observer triggering renders | Throttle handlers, memoize list items |
| Render bursts (>5 in 100ms) | Cascading state updates | Batch updates, review Zustand selectors |
| react-scan: component with >30 renders | Missing memoization or unstable references | useMemo/useCallback, check parent renders |
| react-scan: component with >50ms time | Expensive render function | Split component, move work out of render |
When react-scan identifies a rerender hotspot but you still need the exact file behind a concrete DOM node, hand off to $inspect-elements.
playwright-cli -s=prof-followup eval "async el => JSON.stringify(await window.__ELEMENT_SOURCE__.resolve(el))" e7
Use source.filePath as the direct edit target and stack to understand which parent components own the node.
After profiling is complete and the report is delivered, verify no orphaned processes were left behind:
# Check for any Vite dev servers started during profiling
ps aux | grep 'vite.*--port' | grep -v grep
Also close any leftover playwright-cli sessions:
# Close any profiling sessions that weren't properly closed
playwright-cli -s=prof-1 close 2>/dev/null
playwright-cli -s=prof-2 close 2>/dev/null
playwright-cli -s=prof-3 close 2>/dev/null
-s=prof-N).goto — the profiler collects before navigating away.trace.zip viewable in Trace Viewer.biz, pol, g, a, v, etc. map to subplebbit addresses via the directory.__getReactScanReport returns null, the profiler falls back to commit counts + render bursts (still useful, just no component names).tools
Profile app performance while browsing, collecting Web Vitals and React rerender data via react-scan. Orchestrates parallel profiler subagents via playwright-cli to capture navigation timing, long tasks, layout shifts, LCP, React commit counts, render bursts, and per-component render data. Use when profiling browsing performance, finding bottlenecks, diagnosing excessive rerenders, or auditing page performance.
tools
Automates browser interactions for web testing, form filling, screenshots, and data extraction. Use when the user needs to navigate websites, interact with web pages, fill forms, take screenshots, test web applications, or extract information from web pages.
tools
Create a GitHub issue from recent changes, commit only relevant diffs on a short-lived task branch, push that branch, and open a PR into master that will close the issue on merge. Use when the user says "make closed issue", "close issue", or wants to create a tracked, already-resolved GitHub issue for completed work.
development
Formats GitHub issue titles and descriptions for tracking problems that were fixed. Use when proposing or implementing code changes, creating GitHub issues, or when the user asks for issue suggestions.