# Performance Doctor

> Automated performance audit, diagnosis, and fix for all pages in a frontend project. Runs Lighthouse headless, identifies bottlenecks in source code, generates a baseline report, then optionally iterates fix rounds upon user confirmation.

- Skill: `migoxlab/performance-doctor` (Agent Skill, multi-file: 9 files)
- Install (CLI): `npx skillmds@latest add migoxlab/performance-doctor`
- Raw SKILL.md: https://api.skillmd.com/api/skills/migoxlab/performance-doctor/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: migoxlab (https://skillmd.com/u/migoxlab)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/migoxlab/performance-doctor

---


# Performance Doctor

Automated performance audit → report → (optional) diagnosis & fix loop for frontend projects.
Generates a self-contained HTML report with scoring, iteration tracking, and methodology reference.

## Prerequisites

1. **Node.js**: Version 18+
2. **pnpm**: Package manager
3. **Project**: A Vite-based React project with `react-router-dom` routes

## Workflow Overview

```
Phase 0: SETUP      → Install deps, discover routes, start dev server
Phase 1: EVALUATE   → Run Lighthouse on all pages, analyze, generate baseline report
         ── CHECKPOINT: Present report to user, ASK whether to proceed with optimization ──
Phase 2: ITERATE    → (Only after user confirms) Diagnose + fix + re-audit (up to 3 rounds)
Phase 3: UPDATE     → Regenerate report with iteration data
```

**IMPORTANT**: After Phase 1 you MUST stop and wait for user confirmation before entering Phase 2. Do NOT automatically start fixing code.

---

# Phase 0: Setup

## Step 0.1: Initialize Scripts

```bash
# Copy scripts into the target project
cp -r <skill-dir>/performance-doctor/scripts ./perf-doctor-scripts
cd perf-doctor-scripts && pnpm install && cd ..
```

## Step 0.2: Discover Routes

```bash
node perf-doctor-scripts/discover-routes.mjs --src ./src
```

This scans the project's route config (supports `react-router-dom` v6 `useRoutes` / `createBrowserRouter` patterns) and outputs `perf-doctor-scripts/process/routes.json`.

**AI Task**: Review the discovered routes. Remove any that should be skipped (e.g. catch-all `*`, auth-only pages that can't render without session). Confirm the final route list before proceeding.

## Step 0.3: Detect Dev Server URL

**AI Task**: Before starting the dev server, read the project's `vite.config.ts` (or `vite.config.js`, `vite.config.mts`) to detect the port and base path. Look for:

1. **Port**: `server.port` in the Vite config (default: 5173)
2. **Base path**: `base` property in the Vite config (default: `/`)

Example patterns to look for:
```ts
// vite.config.ts
export default defineConfig({
  base: '/kernelswift',       // → base path is /kernelswift
  server: {
    port: 8080,              // → port is 8080
  },
})
```

Also check for other config files if Vite config is not present:
- `webpack.config.js` → `devServer.port` and `output.publicPath`
- `next.config.js` → `basePath` (port usually 3000)
- `package.json` → scripts section may specify `--port`

Construct the base URL as: `http://localhost:{port}{base}` (strip trailing slash from base).
Example: port=8080, base=/kernelswift → `http://localhost:8080/kernelswift`

If no config is found, default to `http://localhost:5173`.

**Store the detected URL** — you will use it as `--base-url` in all subsequent audit commands.

## Step 0.4: Start Dev Server

```bash
# In a separate terminal, start the project dev server
pnpm dev
```

**Verify**: Dev server is running and accessible at the detected URL from Step 0.3.

---

# Phase 1: Evaluate & Report

## Step 1.1: Run Lighthouse Audit

```bash
# Use the base URL detected in Step 0.3 (example shows default; replace with actual detected URL)
node perf-doctor-scripts/run-audit.mjs \
  --routes ./perf-doctor-scripts/process/routes.json \
  --base-url <DETECTED_BASE_URL> \
  --output ./perf-doctor-scripts/process/baseline.json \
  --round 0 \
  --headers '{"id":"99"}'   # optional: extra headers for auth bypass
```

Options:
- `--headers '<JSON>'` — Extra HTTP headers sent with every request (e.g. auth bypass)
- `--cookies <file>` — Cookie JSON file for session injection
- `--max-wait <ms>` — Max wait for FCP before marking as error (default 30000)

**Verify**: `perf-doctor-scripts/process/baseline.json` exists with audit data for all routes.

## Step 1.2: Baseline Analysis & Overall Diagnosis

**AI Task** — This is critical. You must produce TWO outputs:

### Output 1: Baseline Diagnosis (Markdown)

**SAVE**: Write to `perf-doctor-scripts/process/diagnosis-round-0.md`

Content requirements:
1. **Overall Performance Summary** — A concise paragraph describing the project's overall performance health
2. **Systemic Issues** — Performance problems that affect multiple pages (e.g. large shared bundle, render-blocking resources, heavy framework overhead)
3. **Per-Page Breakdown** — For each page rated C or below:
   - Which metrics are failing and their values
   - Probable root cause mapped to specific code (file path + line number)
   - Priority: critical / high / medium / low
4. **Optimization Roadmap** — Ordered list of recommended fixes by expected impact

### Output 2: Structured Iteration Data (JSON)

**SAVE**: Write to `perf-doctor-scripts/process/iterations.json`

```json
{
  "overallAnalysis": {
    "summary": "One paragraph describing the project's overall performance posture",
    "systemicIssues": [
      {
        "issue": "Description of the systemic problem",
        "impact": "Which metrics are affected (e.g. LCP, FCP)",
        "affectedPages": ["/", "/chat"],
        "severity": "critical | high | medium | low"
      }
    ],
    "recommendations": [
      "Ordered list of recommended optimizations"
    ]
  },
  "rounds": []
}
```

## Step 1.3: Generate Baseline Report

```bash
node perf-doctor-scripts/generate-report.mjs \
  --process-dir ./perf-doctor-scripts/process \
  --output ./perf-doctor-scripts/process/performance-report.html
```

**Verify**: Open `perf-doctor-scripts/process/performance-report.html` in a browser and confirm it renders correctly.

## Step 1.4: CHECKPOINT — Present Results & Ask User

**⚠️ MANDATORY STOP POINT ⚠️**

You MUST stop here and present the evaluation results to the user. Include:

1. A summary table of all pages with their scores and grades
2. The key systemic issues found
3. Top recommended optimizations
4. The path to the full HTML report

Then **ask the user explicitly**:

> "性能评估报告已生成，是否需要进入优化迭代阶段？我会创建独立分支进行代码修改。"

**Do NOT proceed to Phase 2 unless the user explicitly confirms they want optimization iterations.**

If the user says no or wants to stop here, the workflow is complete — the baseline report is the final deliverable.

---

# Phase 2: Iterate & Fix (only after user confirms)

## Step 2.0: Create Fix Branch

Before making any code changes, create a dedicated git branch to preserve all modifications:

```bash
git checkout -b perf-doctor/fix-$(date +%Y%m%d-%H%M%S)
```

**IMPORTANT**: All code fixes in Phase 2 MUST be committed to this branch. After each round of fixes, commit the changes:

```bash
git add -A
git commit -m "perf(doctor): round {N} - <brief description of fixes>"
```

This ensures the user can review, cherry-pick, or revert any optimization changes. Do NOT skip this step.

---

Repeat the following for each round (1, 2, 3). Stop early if:
- All pages reach grade A or above, OR
- A round produces no meaningful improvement (< 3 point gain on any page)

## Step 2.N.1: Diagnose

**AI Task**:
- **READ**: Latest audit JSON (`process/audit-round-{N-1}.json` or `process/baseline.json` for round 1)
- **READ**: Source code of the worst-performing pages (components, route files, data fetching logic)
- **INSTRUCTION**: For each underperforming page:
  1. Identify the root cause of each poor metric (LCP, FCP, CLS, TBT, SI)
  2. Map the cause to specific code locations (file path + line number)
  3. Propose a concrete fix with code changes
  4. Prioritize fixes by expected impact

**SAVE**: Write diagnosis to `perf-doctor-scripts/process/diagnosis-round-{N}.md` with the following structure:

```markdown
# Round {N} Diagnosis

## Summary
One paragraph summarizing what was found and what will be fixed.

## Findings

### [Page Route] — [Metric] — [severity]
- **Root Cause**: What is causing the poor metric
- **Code Location**: `file/path.tsx:line`
- **Proposed Fix**: What will be changed and why
- **Expected Impact**: Which metrics should improve and by how much

## Planned Changes
1. File: `path/to/file.tsx` — Description of change
2. File: `path/to/file.tsx` — Description of change
```

## Step 2.N.2: Apply Fixes

**AI Task**: Apply the proposed code fixes to the project source code. Only change what is necessary — do not refactor unrelated code.

**IMPORTANT**: After applying fixes, record what was changed. You will need this in the next step.

## Step 2.N.3: Re-Audit & Record Iteration

```bash
node perf-doctor-scripts/run-audit.mjs \
  --routes ./perf-doctor-scripts/process/routes.json \
  --base-url <DETECTED_BASE_URL> \
  --output ./perf-doctor-scripts/process/audit-round-{N}.json \
  --round {N} \
  --headers '{"id":"99"}'   # same headers as baseline
```

**AI Task** — After re-audit, you MUST update `perf-doctor-scripts/process/iterations.json`:

Append a new round entry to the `rounds` array:

```json
{
  "round": 1,
  "timestamp": "ISO timestamp",
  "diagnosis": {
    "summary": "One paragraph summarizing this round's diagnosis",
    "findings": [
      {
        "page": "/route",
        "metric": "LCP",
        "rootCause": "Concise description of the root cause",
        "codeLocation": "src/pages/Home.tsx:42",
        "severity": "critical"
      }
    ]
  },
  "changes": [
    {
      "file": "src/pages/Home.tsx",
      "description": "What was changed and why",
      "linesChanged": "42-58",
      "targetMetric": "LCP"
    }
  ],
  "results": {
    "avgScoreBefore": 39,
    "avgScoreAfter": 54,
    "delta": 15,
    "pageDeltas": [
      { "page": "/", "before": 36, "after": 52, "delta": 16 }
    ],
    "effectiveChanges": ["Description of changes that improved scores"],
    "ineffectiveChanges": ["Description of changes that had no effect"]
  }
}
```

Also update `overallAnalysis` if new systemic insights are discovered during this round.

---

# Phase 3: Update Report

## Step 3.1: Final Analysis Update

**AI Task**: Before regenerating the report, review the final state of `iterations.json`:
- Ensure `overallAnalysis.summary` reflects the complete journey (baseline → final state)
- Ensure all rounds have complete data (diagnosis, changes, results)
- Add any final recommendations that weren't addressed

## Step 3.2: Regenerate HTML Report

```bash
node perf-doctor-scripts/generate-report.mjs \
  --process-dir ./perf-doctor-scripts/process \
  --output ./perf-doctor-scripts/process/performance-report.html
```

This regenerates the report, now including iteration data in addition to the baseline:

### Tab 1: Results
- Overview cards: page count, average score, grade distribution, improvement delta
- Per-page table: route / score / grade / all metrics / delta from baseline
- **Overall Analysis** section: summary paragraph + systemic issues list

### Tab 2: Iterations
- If no optimization rounds were performed (user chose not to iterate), shows a message indicating baseline-only evaluation
- If iterations were performed, shows timeline view of each round:
  - **Diagnosis**: What problems were found, mapped to code locations
  - **Changes**: What files were modified, what was changed, why
  - **Results**: Before/after score comparison per page, delta indicators
  - **Effective vs Ineffective**: Which changes worked and which didn't

### Tab 3: Methodology
- Metric definitions and measurement methods
- S/A/B/C/D grade standards (Core Web Vitals + internal S-tier)
- Lighthouse scoring algorithm and weights
- Common performance anti-patterns quick reference

**Verify**: Open the updated `perf-doctor-scripts/process/performance-report.html` in a browser and confirm iteration data is visible.

---

# Grade System

| Grade | Lighthouse Score | Positioning |
|-------|-----------------|-------------|
| **S** | ≥ 95 | Exceptional (internal benchmark) |
| **A** | ≥ 90 | Excellent (industry Good) |
| **B** | ≥ 70 | Acceptable |
| **C** | ≥ 50 | Needs optimization |
| **D** | < 50 | Poor |

### Per-Metric Thresholds

| Metric | S (Exceptional) | A (Excellent) | B (Acceptable) | C/D |
|--------|----------------|---------------|-----------------|-----|
| LCP | ≤ 1.5s | ≤ 2.5s | ≤ 4.0s | > 4.0s |
| FCP | ≤ 1.0s | ≤ 1.8s | ≤ 3.0s | > 3.0s |
| CLS | ≤ 0.05 | ≤ 0.1 | ≤ 0.25 | > 0.25 |
| TBT | ≤ 100ms | ≤ 200ms | ≤ 600ms | > 600ms |
| SI | ≤ 2.0s | ≤ 3.4s | ≤ 5.8s | > 5.8s |

A page gets grade **S** only when ALL core metrics meet S thresholds. Any single metric below S downgrades to A or below.

---

# Data Files Reference

All intermediate data is stored in `perf-doctor-scripts/process/`:

| File | Format | Purpose |
|------|--------|---------|
| `routes.json` | JSON | Discovered routes list |
| `baseline.json` | JSON | Round 0 Lighthouse audit data |
| `audit-round-{N}.json` | JSON | Round N Lighthouse audit data |
| `diagnosis-round-{N}.md` | Markdown | Human-readable diagnosis for round N |
| `iterations.json` | JSON | Structured iteration data (fed into report) |
| `performance-report.html` | HTML | Final self-contained report |

---

# Troubleshooting

| Issue | Solution |
|-------|----------|
| Chrome not found | Run `npx playwright install chromium` in `perf-doctor-scripts/` |
| Dev server not responding | Ensure `pnpm dev` is running and the port matches `--base-url`. Re-check `vite.config.ts` for the correct port and base path |
| Route requires auth | Add auth cookies via `--cookies cookies.json`, or add extra headers via `--headers '{"id":"99"}'` |
| Lighthouse timeout | Increase `--timeout` flag (default 60s) or check if page has infinite loading |
| No improvement after 3 rounds | Some bottlenecks (server response, third-party scripts) can't be fixed in frontend code alone — document them in the report |

