An engineering-led performance & UX consultancy. We pull field data from your real users, find the regressions Lighthouse misses, and ship the fixes against your repo — usually inside one two-week sprint.
Every engagement starts with field data and ends with a verified delta in your RUM dashboard. No vanity scores, no Lighthouse hero numbers, no theatrics.
A focused two-week engagement targeting your three worst Core Web Vitals on the highest-traffic templates. Fixed scope, fixed price, PRs against your repo.
Heuristic + session-replay audit of your conversion-critical flows. We benchmark friction points against your funnel data and hand you a sequenced fix list.
Ongoing monitoring + monthly fix cycles. We watch your p75 LCP, INP and CLS, catch regressions inside 48 hours, and ship a fix before the CrUX window closes.
End-to-end six-week program combining perf, UX and conversion work. For teams who want one accountable partner across the entire optimization surface.
We treat your site like a system under load. Each step has explicit inputs, explicit outputs, and a tool stack we'll happily defend in a code review.
Pull 28 days of field data from CrUX, plus your existing RUM if you have one. Establish p75 baselines for LCP, INP, CLS, TTFB across device class and template.
Reproduce in a throttled Chrome profile (Slow 4G, 4× CPU). Capture long tasks, layout shifts, render-blocking chains. Cross-reference with synthetic Lighthouse runs.
Rank candidate fixes by estimated impact on p75 LCP/INP divided by eng-days. We size each one against a perf budget and pick the top 8–14 for the sprint.
Branch, code, PR. Each PR includes a Lighthouse CI gate, a bundle-size diff, and a written hypothesis. Your team reviews and merges on its normal cadence.
Wait one CrUX window (28 days) and pull field data again. We report the delta against the original baseline, attribute revenue impact, and flag any regressions.
No client logos here — most of our work is under NDA — but every metric below is verified in the client's RUM dashboard, not a Lighthouse run on a fresh laptop.
Hydrogen storefront with a 480KB hero image, blocking Klaviyo script in <head>, and a font-loading strategy that swapped twice. We shipped responsive AVIF, deferred Klaviyo to interaction, and inlined the critical font subset. The 0.6pt conversion lift translates to meaningful six-figure annual revenue at their volume.
2-week sprint · shipped Feb 2026Docusaurus build with a heavyweight search index hydrating on every page. We replaced client-side Algolia hydration with a deferred web-worker load, code-split the syntax highlighter by language, and rebuilt the sidebar with CSS-only collapse. INP dropped below the 200ms "good" threshold across all geographies inside one CrUX window.
3-week sprint · shipped Nov 2025A 12-year-old Next.js publication with GAM ad slots that reflowed three times per article load. We reserved aspect-ratio boxes for every slot, moved the consent banner out of the critical render path, and rebuilt the related-articles widget as a server component. Reader session time up 18%, ad RPM up 28%.
4-week engagement · shipped Aug 2025We track the same fourteen signals on every engagement. Targets are field-data p75 unless noted — synthetic numbers are for debugging, not for grading the work.
| Metric | What it measures | Good threshold | Tool / source |
|---|---|---|---|
| LCP | Largest Contentful Paint — time to hero element | < 2.5s | CrUX · web-vitals.js |
| INP | Interaction to Next Paint — input responsiveness p98 | < 200ms | CrUX · web-vitals.js |
| CLS | Cumulative Layout Shift — visual stability over session | < 0.1 | CrUX · LayoutShift API |
| TTFB | Time to First Byte — server + edge response time | < 800ms | Navigation Timing API |
| FCP | First Contentful Paint — first text/image render | < 1.8s | CrUX · Paint Timing |
| TBT | Total Blocking Time — main-thread work during load | < 200ms | Lighthouse · DevTools |
| JS bundle (gz) | First-party JavaScript shipped on initial route | < 170KB | bundlewatch · Calibre |
| Image weight | Total image bytes on viewport-critical path | < 500KB | WebPageTest · DevTools |
| Long tasks | Main-thread tasks blocking interaction > 50ms | < 3 per page | Long Tasks API |
| Bounce rate | Single-page sessions, segmented by entry template | site-relative | GA4 · Amplitude |
| Conversion | Primary goal completion rate, by device class | site-relative | GA4 · Shopify · Stripe |
| AOV | Average order value — perf often correlates strongly | site-relative | Shopify · Stripe |
| Scroll depth | % of users hitting 25/50/75/100% scroll on key pages | site-relative | GA4 events · custom |
| Rage clicks | Repeated clicks on non-responsive elements per session | < 1.5% | FullStory · LogRocket |
All quotes from people who reviewed and merged our PRs themselves. Names and companies on request — many engagements are under NDA.
Site Upgrade landed seventeen PRs against our monorepo in two weeks. Every one had a benchmark, a budget, and a Lighthouse CI gate. The team didn't need any handholding — they read our codebase faster than half our new hires.
Our p75 LCP had been stuck at 4.2s for eighteen months. Emma's team got us to 2.0s in a sprint, and more importantly explained which fix moved the number so we could keep the discipline ourselves. Best money I've spent on the site.
I've worked with three perf consultancies over the years. Site Upgrade is the first one that treated our codebase like a real engineering surface — not a slide deck. They opened PRs against the right branches and let our team review on our own clock.
If yours isn't here, email team@siteupgrade.co — Emma replies herself, usually within a business day.
No. We ship in tight branches, raise PRs against your repo, and gate every change on a perf budget you control. Your team reviews and merges on its own cadence. We've never blocked a client release — and several clients have told us our PRs are cleaner than their average internal one because every change carries an explicit hypothesis and a measured delta.
Yes. We have shipped production work against Next.js, Remix, Astro, Nuxt, SvelteKit, Shopify Hydrogen, Shopify Liquid, WordPress (classic and headless), Webflow, and bespoke Rails / Django / Laravel front-ends. About 80% of the wins are stack-agnostic — image strategy, font loading, third-party deferral — so we rarely have to ask you to migrate anything.
Field data first. We pull 75th-percentile LCP, INP and CLS from CrUX and from our own web-vitals.js beacon (we'll instrument it on day one if you don't already have RUM). Business KPIs second: conversion rate, AOV, bounce, scroll depth, and any custom funnel events you already track in GA4 or Amplitude. We report the delta against a 28-day pre-engagement baseline.
Absolutely — about 30% of our engagements run in parallel to a design, brand or growth agency. We stay narrowly in the performance and UX optimization lane and document every change with a written hypothesis, so the other team can see exactly what shipped and why. We've co-existed with everyone from boutique brand studios to Big Four consultancies without stepping on toes.
Then we shift the focus. Sites that already pass Core Web Vitals usually still leak 8–15% of potential revenue to interaction latency under real load, layout instability on logged-in pages, or unmeasured UX friction in the conversion funnel. We'll happily run a free 30-minute audit and tell you honestly whether there's enough headroom to be worth a sprint.
We do the work. Our small dev team writes the code, opens the PR, and stays on the engagement until field data confirms the fix landed — typically inside 14 days of merge. Reports are an output, never the deliverable. If you want a report-only engagement, we'll happily refer you to one of the larger audit shops that specialize in that.
We'll run a free 30-minute audit, pull your CrUX data, and tell you honestly whether a sprint is worth your money. No deck, no upsell — just a Loom walkthrough of what we'd ship and why.
Fixed price, no surprises — figured out on the intro call.