A demo app for React Summit 2025. It is a sneaker storefront intentionally built with every common image performance mistake. You run it, measure the damage in Chrome DevTools, then use two MCP servers inside Cursor to audit, identify, and fix the issues.
git clone https://github.com/imagekit-samples/broken-on-purpose
cd broken-on-purpose
pnpm install
pnpm devOpen http://localhost:5173. Open Chrome DevTools, Network tab, disable cache, hard reload. Count the megabytes.
No ImageKit account needed for this step. The demo assets are served from a public ImageKit CDN endpoint we maintain.
You'll need Cursor, Node 20.19+, and a free ImageKit account for the private key.
- Sign up at imagekit.io (free tier is fine).
- Copy your private API key from the developer options page.
- Open
.cursor/mcp.jsonand paste your key in theIMAGEKIT_PRIVATE_KEYenv var. - Open the repo in Cursor. Go to Settings → Tools & MCP. Confirm both servers are green.
- Run the five prompts below in Cursor Composer.
Your private key only unlocks the MCP's tools. The URL transformations it generates work against our public demo CDN, so you won't be uploading anything to your own account.
Paste these into Cursor Composer one at a time. Read the agent's output as it goes.
Use the chrome-devtools MCP to record a performance trace of
http://localhost:5173 and tell me the three biggest performance
issues ranked by user impact.
The agent navigates to the page, records a performance trace, and analyzes it with performance_analyze_insight (which pulls real-user field data from the CrUX API to sanity-check the lab trace). Expect it to name LCP, CLS, and total transfer size as the top three issues.
For each issue, tell me the specific image URL and the exact DOM
selector of the element causing it.
The agent inspects the network waterfall and the DOM snapshot to name specific assets: hero.jpg, thumb-featured.png, and the 10 product thumbnails. This is the difference between a checklist ("your images are big") and an audit ("this URL, this selector, this impact").
Invoke the fix phase. Use the imagekit MCP's docs search to look up
the right transformation parameters, then use the code tool to
generate URLs via the ImageKit Node SDK. Write helper functions in
src/lib/images.ts that wrap the raw ImageKit URLs with the correct
transformations for hero images, product thumbnails, and product
detail images. The SDK validates parameters as it builds each URL.
The agent searches the ImageKit transformation docs for the right parameters, then uses the SDK's URL builder to generate validated URLs. Output goes into src/lib/images.ts as three helpers: buildHeroUrl, buildProductThumbUrl, buildProductDetailUrl.
Now update Hero.tsx, ProductCard.tsx, and ProductDetail.tsx to use
the helpers from src/lib/images.ts. Add width and height attributes,
fetchpriority="high" on the hero, and loading="lazy" on below-fold
images.
The agent edits the three components to use the new URL helpers and adds the missing image attributes for layout stability and loading priority.
Rerun the performance trace and show me the before/after comparison.
The agent records a fresh trace and hands you the delta. This is the moment the numbers collapse.
- Vite + React 18 + TypeScript
- React Router v7 for the home and product detail routes
- Tailwind CSS v4 for styling
- Two MCP servers configured in
.cursor/mcp.json
Exposes Chrome DevTools as tools any agent can call. We use four of them:
performance_start_trace/performance_stop_trace: record a timelineperformance_analyze_insight: extract actionable issues, enriched with CrUX field datalist_network_requests: inspect the waterfalltake_snapshot: get the accessibility tree for selector identification
Full tool reference: ChromeDevTools/chrome-devtools-mcp.
Ships as @imagekit/api-mcp. Uses "Code Mode": two tools, one for docs search and one for a TypeScript sandbox where the agent writes code against the ImageKit Node SDK. URL validation happens inside the SDK during URL construction, not via a separate validator call.
Full docs: imagekit.io/docs/mcp-server.
Every mistake below is load-bearing for the demo.
| Pattern | Where | Impact |
|---|---|---|
<img> tags with no width/height |
Every component | Cumulative Layout Shift |
<img> tags with no loading attribute |
Product grid below the fold | Bandwidth waste, slow LCP |
<img> tags with no fetchpriority |
Hero | Delayed LCP |
ImageKit URLs with tr=orig-true |
All components | Forces original file — bypasses auto format conversion and quality |
| A 4 MB PNG serving a photo | thumb-featured.png |
20x the bytes AVIF would use |
<video autoplay> with no lazy strategy |
Hero | Blocks main thread at page load |
No <picture> with AVIF/WebP sources |
Hero and cards | Browser never gets a modern format |
The Cursor rules in .cursor/rules/do-not-optimize.mdc keep the agent from "helpfully" fixing these during normal coding sessions. They only get fixed when you explicitly invoke the fix phase.