Hold it to a performance budget on a real phone
Continues from the last build: a searchable app with no performance guardrails
Last rung you shipped a fast, accessible search over the event stream, and on your laptop, on your office wifi, it feels instant.
What you'll build
A committed performance budget file, a Lighthouse CI config that runs on a throttled mobile profile and fails on regression, a lazily-loaded chart chunk that stays out of the initial bundle, a below-the-fold section that defers its own render until it is near the viewport, reserved layout space so nothing shifts when async content arrives, and a TanStack Query cache tuned to stop redundant refetches.
See how we teach, before you sign up
You don't just get code dumped on you. Every starter file and every solution is explained line-by-line, in plain English. Here's one real file from this project:
{
"ci": {
"collect": {
"numberOfRuns": 3,
"settings": {
"preset": "mobile",
"throttlingMethod": "simulate",
"throttling": {
"cpuSlowdownMultiplier": 4,
"rttMs": 150,
"throughputKbps": 1638.4
}
}
},
"assert": {
"assertions": {
"largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
"cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }],
"interactive": ["error", { "maxNumericValue": 4000 }],
"resource-summary:script:size": ["error", { "maxNumericValue": 180000 }]
}
},
"upload": {
"target": "temporary-public-storage"
}
}
}Reading this file
"cpuSlowdownMultiplier": 4,Simulates a mid-tier Android CPU, not the M-series chip on your laptop. This is the setting that stops you from measuring on fast wifi only."throughputKbps": 1638.4Caps the simulated network around a slow 4G connection instead of your fast office wifi."largest-contentful-paint": ["error", { "maxNumericValue": 2500 }]The LCP budget as a hard error, Lighthouse CI fails the run instead of just reporting a number."resource-summary:script:size": ["error", { "maxNumericValue": 180000 }]The initial JS ceiling, this is the number that forces the chart out of the main bundle in milestone 3."cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }]The CLS budget, tied directly to the reserved-space work you do in milestone 4.
Runs Lighthouse three times on a simulated mid-tier Android profile and fails the run if any metric or the initial JS weight crosses the line.
That's 1 of 8 explained code blocks in this single project.
The build, milestone by milestone
- 1
Write the budget as a pass or fail contract
4 guided stepsA budget that lives only in your head gets renegotiated the moment a deadline is tight. A budget that is a typed constant and a CI assertion cannot be quietly ignored, it either passes or the build fails.
- 2
Measure an honest baseline on a throttled profile
4 guided stepsYou cannot fix what you have not measured honestly. Fast wifi and a laptop CPU hide exactly the problems a real user hits, the baseline has to reproduce the pain before you can prove you removed it.
- 3
Code-split the heavy chart out of the initial bundle
4 guided stepsA pass/fail JS ceiling only matters if something is actually forcing weight out of the critical path. The chart is almost always the biggest single offender in an analytics console, splitting it is usually the single highest-leverage fix.
- 4
Kill the layout shift when charts and late data mount
4 guided stepsA user does not experience 'the bundle is smaller', they experience 'the button I was about to tap just moved'. CLS is the metric that most directly measures that feeling, and it is the easiest one to accidentally make worse while fixing JS weight.
- 5
Cache honestly and trim dependency weight
4 guided stepsEvery unnecessary refetch and every kilobyte of an unused dependency chips away at the same JS and interaction budget you just fought to hit. Caching and trimming are the parts of the fix that keep paying off after this rung ends.
- 6
Wire the budget into a CI gate that fails the build
4 guided stepsA budget that a human has to remember to check gets skipped the first time a release is late. A budget wired into CI either blocks the merge or it does not exist.
What's inside when you start
You'll walk away with
This is portfolio-grade. Build it free.
Sign up to unlock every milestone step-by-step, the code skeletons, full reference solutions, and checkable tasks, with your progress saved as you build.
Start building