Field data
Judged at the 75th percentile
A page passes Core Web Vitals when at least 75% of visits are good, using the Chrome UX Report’s rolling 28 days. Our own monitoring adds every template, device class and release.
Capability 01 of 10Technology & Intelligence
Websites, web and mobile apps that stay fast, accessible and secure after launch. Performance budgets, accessibility checks and live monitoring start in the first sprint, so what is fast in the demo is still fast 90 days after launch.
Illustration: the same “Your platform” product page on a desktop browser, a tablet and a phone, each laid out for its screen. Field data at the 75th percentile is good on all three: desktop LCP 1.2 seconds, INP 60 milliseconds, CLS 0.01; tablet LCP 1.7 seconds, INP 110 milliseconds, CLS 0.02; mid-range Android phone on 4G LCP 1.9 seconds, INP 140 milliseconds, CLS 0.04. Values are illustrative.
01 · After launchMobile LCP · 75th percentile · first 90 days
A site can score 98 on a fast laptop and still slow down as tags, video and scripts are added. We judge the work by the 75th percentile of visits, tracked daily.
p75 LCPLargest Contentful Paint, seconds, per day
Line chart, illustrative. Over 90 days after launch, an unmanaged site’s mobile LCP at the 75th percentile rises from 2.2 to 5.1 seconds, stepping up at each event below and ending in the poor band. A site with performance budgets in CI stays between 2.1 and 2.5 seconds, in the good band.
Unmanaged5.1 sPoor
Budgeted in CI2.1 sGood
1Day 12
Marketing tags added
Unmanaged +0.5 s
Loaded after consent · +0.1 s
2Day 34
Autoplay hero video
Unmanaged +0.9 s
Blocked by the budget · poster image used
3Day 58
Client-side A/B test script
Unmanaged +0.5 s
Moved to the edge · no browser script
4Day 77
Chat widget on every page
Unmanaged +0.5 s
Loads on first interaction


Field data
A page passes Core Web Vitals when at least 75% of visits are good, using the Chrome UX Report’s rolling 28 days. Our own monitoring adds every template, device class and release.
Responsiveness
Interaction to Next Paint became a Core Web Vital on 12 March 2024. It times every interaction in a visit, so heavy JavaScript now shows. Good is 200 ms or less.
Budgets
Lighthouse CI and bundle-size limits run on every pull request. A change that breaks the budget cannot merge until it is deferred, compressed or removed. Alerts watch live speed after each release.
02 · What we buildSix services · one set of checks
Each starts from the same base: a design system in code, performance budgets, accessibility checks and monitoring from the first release.
01
Server-rendered or static sites on a headless CMS, with structured content, editor previews and edge caching that holds as pages multiply.
02
Customer portals, dashboards and SaaS products with typed APIs and role-based access that keep working on patchy networks.
03
Native iOS and Android apps, or one Flutter or React Native codebase, chosen by device features, offline needs and team skills.
04
Shopify or headless storefronts, with search, product pages and checkout tuned for low-end phones.
05
Installable web apps that queue work offline and sync when the connection returns, so field teams keep working.
06
Tokens and components shared by web and mobile, documented in Storybook and tested for accessibility on every change.
03 · Speed demoInteractive · illustrative model
Pick a device and network, then switch on the work we put into every build. The filmstrip shows the page appearing, the gauges score it against Core Web Vitals and the log lists each gain.
Device class
Network
Optimisations6 of 6 on
Filmstrip · one frame every 0.6 s
LCPLargest Contentful Paint
2.1 sGood
INPInteraction to Next Paint
160 msGood
CLSCumulative Layout Shift
0.03Good
Page weight0.93 MB
Server wait (TTFB)590 ms
First Contentful Paint1.2 s
Est. gCO2e per view0.20 g
Core Web Vitals assessment · field distribution
Passedall three at p75 must be good
What changednewest first
An illustrative model, not a measurement of any site. Thresholds are Google’s Core Web Vitals at the 75th percentile: good is LCP ≤ 2.5 s, INP ≤ 200 ms and CLS ≤ 0.1; poor is above 4 s, 500 ms and 0.25. A page passes when all three are good; page loads are assumed to spread log-normally around each value. Emissions use the Sustainable Web Design method for a first, uncached view: 0.494 kWh per gigabyte transferred at a global-average 442 gCO2e per kilowatt-hour, about 218 gCO2e per decimal gigabyte (1 GB = 1,000,000 KB). §08 uses the same two numbers.
04 · Tech stackOne request · mobile · 4G · budget per step
Each technology sits at one step of a page request, with a time budget. Pick a step to see why we use it; the trace below times one request from tap to paint.
Diagram: a request travels from the device through the edge cache, server rendering, APIs and the database, and every step reports to observability. Each step carries a time budget: device hydration 150 milliseconds, edge 30, rendering 180, APIs 120 at the 95th percentile, data 40 per query, observability overhead 5. Values are illustrative targets.
01≤ 150 ms to hydrate
The least code that does the job: Astro or Next.js by how much JavaScript a page needs; Flutter or React Native when one codebase serves both app stores; Swift and Kotlin for camera, sensor and background-heavy apps.
How we hold the budgetBundle-size limit per route in CI · only interactive parts hydrate · INP measured on live visits
Technologies we work with at this step
02≤ 30 ms at the edge
Pages and files are cached close to users, so most requests never reach a server and each release clears only what changed. Cloudflare or Vercel to match your traffic and team; Fastly or Akamai if you already have a contract.
How we hold the budgetCache-hit ratio on the dashboard · stale-while-revalidate for content · immutable asset URLs
Technologies we work with at this step
03≤ 180 ms to first byte
HTML arrives ready to display. The page frame streams before the data, so the browser loads fonts and the main image while the product query runs. Next.js for full applications; Astro for content sites that need almost no JavaScript.
How we hold the budget95th-percentile render time per template · streaming by default · no chained data calls in the browser
Technologies we work with at this step
04≤ 120 ms p95 per page
One typed contract, GraphQL or OpenAPI, links the front end to every service behind it. Calls are combined and briefly cached, so a busy product page costs one round trip. A headless CMS or Shopify plugs into the same contract.
How we hold the budgetContract tests in CI · N+1 queries fail the build · calls batched per page
Technologies we work with at this step
05≤ 40 ms p95 per query
PostgreSQL, indexed for the queries the app runs, with Redis for sessions, carts and frequently read data. Every query has a time budget and an alert, so a table that grows tenfold is caught before customers notice.
How we hold the budgetSlow-query log reviewed each sprint · migrations rehearsed on a production copy
Technologies we work with at this step
06≤ 5 ms overhead
OpenTelemetry gives every step one trace ID, so a slow page can be followed from tap to query. Sentry links each error to the release behind it; Datadog records speed on live visits. Sampling keeps the overhead under five milliseconds.
How we hold the budgetOne trace ID across steps · release tagged on every error · 75th-percentile alerts per template
Technologies we work with at this step
One request, tracedfirst visit · mid-range Android · 4G · trace-id 7f3a…c21e
First byte 120 msHTML complete 212 msLCP 1.9 sIllustrative
Trace of one page request, illustrative: DNS, TLS and the request take the first 38 milliseconds; the edge cache lookup misses at 52; the rendering shell streams by 120 milliseconds while three API calls run in parallel to 165 and the database answers by 96; the HTML is complete at 212 milliseconds; the device paints the largest element at 1.9 seconds; the trace exports asynchronously.
Before release
Built, tested and budget-checked in the pipeline, so only code that passes every check reaches the edge.
05 · Everyday useFour contexts · four requirements
Your users are rarely at a desk on a fast connection. We design and test for four contexts and set each one’s requirements before any code is written.

Context 01 · Warehouse floor
Gloves, glare and coverage that drops behind the racking.
Requirement

Context 03 · Operations desk
Two monitors, dense tables and a keyboard that rarely leaves the hand.
Requirement

Context 02 · Commute
One hand, one thumb and a network that comes and goes between stations.
Requirement

Context 04 · Bus stop
Bifocals, cold hands and the text zoomed to 200%.
Requirement
06 · Quality gatesSeven checks · set as numbers · run on every change
Each gate is a written limit in your repository, set in kilobytes, seconds or number of failures. The queue checks each change as it will be once merged. Pick a change to see its results.
Illustrative pull requestsIllustration of a merge queue holding three pull requests against seven written limits. Pull request 412, gallery zoom and AVIF hero images, is first in line and meets every limit. Pull request 414, faceted filters on the listing page, sends 318 kilobytes of JavaScript against a 250 kilobyte limit, so the queue holds there. Pull request 415, a dependency update, passes every gate but waits third. The other six limits are zero accessibility violations, zero unreviewed pixel changes, zero failing or flaky tests of 1,380, zero critical or high security advisories, a 1.8 second cold start at the 75th percentile on a Pixel 6a and zero broken redirects of 1,240 rules. An agent proposes lazy-loading the filter panel, which takes 414 to 226 kilobytes and releases the queue; a person commits it.
Merge queue · your-platform / web held at #414
A queue merges the result, not the branch: each change is rebased onto the one in front and rechecked, so two changes that pass alone cannot break main together.
#412Engineer · 3 commits · +412 −96
A code owner approved it at 14:02. The queue updates it with the latest code and reruns every gate, so it merges exactly as tested.
#414Engineer · 7 commits · +1,204 −212
The listing page sends 318 KB of JavaScript against a 250 KB limit. The queue holds, and nothing behind it merges until the limit is met or the change is dropped.
#415Agent-opened · 1 commit · +18 −18
Every gate passes, but it waits its turn. It merges once #414 clears or an engineer removes #414 from the queue.
What WCAG 2.2 adds to the accessibility gate
| Criterion | Level | What it means in the build |
|---|---|---|
| 2.4.11Focus Not Obscured (Minimum) | AA | Sticky headers and cookie bars never hide the focused element. |
| 2.5.7Dragging Movements | AA | Every drag has a click or keyboard alternative. |
| 2.5.8Target Size (Minimum) | AA | Targets at least 24 × 24 px; we build to 44 px on touch. |
| 3.2.6Consistent Help | A | Help and contact sit in the same place on every screen. |
| 3.3.7Redundant Entry | A | Nothing already entered is asked for twice in a flow. |
| 3.3.8Accessible Authentication (Minimum) | AA | Sign-in never depends on memorising or transcribing. |
Where the limits come from
Each limit comes from a published standard. Kilobyte and second limits come from Core Web Vitals at the 75th percentile, and the accessibility limit from WCAG 2.2 AA. Security limits follow OWASP ASVS Level 2 and the OWASP Top 10; delivery measures follow DORA. Mobile builds are also checked against OWASP MASVS, and we report quality against ISO/IEC 25010. We build to these frameworks; the badges are our own marks and do not mean certification.
07 · How we use AIAgents draft · engineers approve · releases are monitored
Agents draft components from the design system, end-to-end tests and a summary of each visual change; engineers edit and review them. After release, field data from your visitors decides whether a change stays.
Illustration of one pull request moving through the release lane in a day. At 09:10 a designer approves the design. At 09:38 an agent drafts the component from design-system tokens; at 10:05 an engineer edits it. At 10:40 an agent drafts fourteen Playwright tests, which the engineer reviews. At 11:12 a preview is live with every gate passed. At 14:30 a person checks the AI summary of the visual changes. At 15:02 a person merges it; agents cannot merge. On Thursday the release rolls out under real-user monitoring and rolls back automatically if 75th-percentile Interaction to Next Paint rises more than 20 percent. Times and values are illustrative.
Thu 10:0010% → 50% → 100%, watched by real-user monitoring
Tokens the draft used, and what they resolve to
AddressCard.tsx · 3 files drafted+1 −5 by an engineerA raw value fails review
An agent drafts an AddressCard component from the design-system tokens in the Figma frame, using space.4 for padding, radius.md for the corner, text.label for the name and the neutral badge tone; an engineer then edits the empty state to add a hint and an action. A raw value in place of a token fails review.
saved-address.spec.ts · drafted by an agent2 assertions tightened by an engineerNo test counts until a person has read it
An agent drafts fourteen Playwright specs covering keyboard use, 320 pixel reflow, screen-reader announcements, focus visibility, target size, 200 percent zoom, reduced motion, validation and a dropped connection. Each spec runs on four device profiles — Chromium and WebKit on the desktop, Pixel 7 on Android and iPhone 15 on iOS — so fifty-six runs pass in total, and an engineer reviews each spec before it counts.
AI summary · 3 visual changes · 0 unexpected
Engineer confirmed against the diff · 14:30
p75 INP · mobile · release 43Illustrative
RUM guard · p75 INP · 10% rampRollback 48 s, automaticIncident note drafted by an agent, owned by a person
Chart of p75 Interaction to Next Paint for the hour after release 43 reaches 10 percent of traffic. It holds near the 150 millisecond baseline, rises to 205 milliseconds at 22 minutes, crosses the 180 millisecond guard, and the release rolls back automatically to release 42 in 48 seconds. INP returns to 150 milliseconds by 30 minutes, and an engineer owns the fix.
Branch protection needs a code-owner approval. Agent accounts can open, comment and suggest; they cannot approve or merge.
Prompts, tool calls and diffs stay attached to the pull request, so the reviewer sees what the agent saw.
We use enterprise AI tools with data retention off. No client code goes into a tool that trains on it.
Monitoring reverts a slow or failing release in under a minute. A person decides what goes out next, and when.
Delivery tools · technologies we work with
08 · Page weightOne product page · six ceilings · modelled
Page weight affects speed, hosting cost and emissions at once, so we set it as a number the build must meet. Choose a ceiling to see what meeting it takes and what the build refuses.
Illustrative modelA model of one product page under six page-weight ceilings. With no ceiling it weighs 4.10 megabytes: images 2,180 kilobytes, JavaScript 1,120, third-party scripts 480, fonts 260, CSS 92 and the document 66. Under a 2.00 megabyte ceiling it weighs 2.00; under 1.50 it weighs 1.49; under 1.00 it weighs 0.90, the ceiling we usually set, with no feature lost; under 0.75 it weighs 0.64 and the gallery loads on interaction; under 0.50 it weighs 0.42 and the page drops its client framework and every third-party script. Across one hundred thousand views the 4.10 megabyte page transfers 420 gigabytes and emits an estimated 92 kilograms of carbon dioxide equivalent, against 92 gigabytes and 20 kilograms at 0.90 megabytes: about 0.92 grams per view against 0.20. The figures are modelled with the Sustainable Web Design methodology, not measured. The table below lists every ceiling.
The ceiling we usually set. Every feature stays and the page is 78% lighter than at the start.The build refuses: Any image over 200 KB. Any page bundle over 250 KB.
| Resource | No ceiling | 1.00 MB | What it takes |
|---|---|---|---|
| Images | 2,180 KB | 402 KB | AVIF with sizes tuned per breakpoint; the hero preloaded, the rest lazy |
| JavaScript | 1,120 KB | 214 KB | Streamed server rendering; only the cart and the gallery hydrate |
| Third-party | 480 KB | 148 KB | Analytics and consent only, both self-hosted |
| Fonts | 260 KB | 62 KB | One subset variable font, woff2, with font-display: swap |
| CSS | 92 KB | 54 KB | Critical CSS inlined; the rest loaded asynchronously |
| Document | 66 KB | 42 KB | Streamed, with no render-blocking inline data |
| Total | 4.10 MB | 0.90 MB | Every view, for as long as the page lives |
How the estimate is made
Transfer is page weight multiplied by views, in decimal gigabytes. Emissions follow the Sustainable Web Design methodology with two inputs: 0.494 kWh per gigabyte transferred and 442 gCO₂e per kilowatt-hour (a global-average grid), about 218 gCO₂e per gigabyte. The simulator in §03 uses the same inputs. The result is an estimate: a cached page served from a low-carbon region emits far less, and a first load on an old device emits more. We report the model and its inputs with every estimate, and we track what we can control: bytes.
SCI = ((E × I) + M) per REnergy multiplied by grid intensity, plus embodied carbon, divided by the unit of work. The Green Software Foundation’s Software Carbon Intensity specification, ISO/IEC 21031:2024.
We align delivery with these frameworks; the W3C Web Sustainability Guidelines shape the practices below.
All six ceilings · one product page
AVIF or WebP at responsive sizes, with set dimensions so nothing shifts and lazy loading below the fold. Images are usually over half the weight.
Streamed server rendering, code split by page and island hydration. The build fails if a bundle grows past its ceiling.
Self-hosted woff2, subset to the characters the site uses, with text readable before the font loads. System fonts where the brand allows.
Every tag has an owner and a review date. Tags with no measurable purpose are removed; the rest load only after the visitor interacts.
Versioned files cached for a long time, refreshed in the background at the edge and served from a CDN close to your visitors.
No autoplay video on mobile, dark mode respected on OLED screens and reduced motion when visitors ask. Less work on the device means less battery drawn.
The build enforces the ceiling. Image, script and font limits sit in the repository and are checked on every pull request by the gate shown in §06. A change that pushes the page over its ceiling fails the build, so a year of small additions cannot push the weight back up.
09 · How we work with youFive stages · each ends with a file you keep
Four stages get the product live; the fifth, ninety days after launch, uses live traffic to fix what has slowed. Each stage ends with a file you can open and a person's sign-off.
Typical timings · sample artefacts01Discover · Wk 01–02
We study your analytics, support tickets and the devices and networks your customers use. That sets the performance budget, the oldest supported browser and the first release.
Before we move on

The artefact you receive
What you get
Signed off byYour product owner and our delivery lead
02Design · Wk 02–05
We design with your content and the design system, then test a prototype with five to eight users. Contrast, target size and focus order are designed in.
Before we move on
The artefact you receive
What you get
Signed off byYour product owner, our design lead and our principal engineer
03Build · Wk 04–11
Agents draft components and tests; engineers review and merge. Each change gets its own preview link, and each sprint ends with a demo.
Before we move on
The artefact you receive
What you get
Signed off byYour product owner, at the demo
04Launch · Wk 11–12
We release to a share of traffic first and monitor Core Web Vitals and errors. If either crosses its limit, the release rolls back automatically.
Before we move on
The artefact you receive
What you get
Signed off byYour product owner and our delivery lead
05Improve · Wk 12+
At day 90, live traffic shows which pages slowed and where people stall. We review it with you, fix the top three regressions and reset the budgets.
Before we move on
The artefact you receive
What you get
Signed off byYour product owner and our delivery lead, at the review
01 / 05 · Discover
10 · What you getSix folders · your repository · your accounts
Your engineers can clone it on day one: the code, tests, performance budgets, runbooks and decision records that explain each technical choice.
What we make for you is yours once it is paid for. Tools we already had stay ours, and you get a free, permanent licence to use them.
11 · What changesTargets we design to · 75th percentile
We write three targets into the plan and check them against your live traffic, each from its own data source. They guide design and budget; they are not promised results.
Targets with sample readings · IllustrativePerformance budgets are checked on every merge and measured on the devices and networks your visitors use.
All three Core Web Vitals “good” at the 75th percentile
Sample distribution of page loads by Core Web Vitals band. Largest Contentful Paint: 78 percent good, 15 percent needs improvement, 7 percent poor, with a 75th-percentile value of 2.1 seconds against a 2.5 second threshold. Interaction to Next Paint: 84 percent good, 11 needs improvement, 5 poor, p75 164 milliseconds against 200. Cumulative Layout Shift: 91 percent good, 6 needs improvement, 3 poor, p75 0.04 against 0.1. All three clear the 75 percent line, so the URL passes the assessment.
Targetat least 75%
Google treats a URL as passing when, at the 75th percentile, LCP ≤ 2.5 s, INP ≤ 200 ms and CLS ≤ 0.1: at least three in four page loads in the good band. We hold that on every template that carries your traffic.
Crash reporting is set up before the first release, with readable stack traces and an owner for every alert. The release guard catches regressions before store reviews do.
Crash-free sessions, mobile, rolling 7 days
Sample seven-day line of crash-free mobile sessions against a 99.5 percent floor: Monday 99.72, Tuesday 99.68, Wednesday 99.81, Thursday 99.42, Friday 99.63, Saturday 99.78, Sunday 99.74. Thursday is the only day below the floor; a release regressed, the guard rolled it back and the line recovered the next day.
Targetat least 99.5%
The floor is 99.5% because, for a busy app, the gap from 99.0% is thousands of broken sessions a month. On Thursday a release regressed and the guard rolled it back within a day.
Small releases behind feature flags, a preview for every change and automatic rollback triggered by real-user data.
Time to restore service after a bad release
Sample histogram of the last eighteen unplanned restores of service: nine under five minutes, six between five and fifteen, two between fifteen and thirty, one between thirty and sixty, none over an hour. Fifteen of the eighteen are inside the fifteen-minute target.
Targetunder 15 minutes
Time to restore is one of the four DORA delivery metrics, and we report all four. DORA’s highest band is under one hour; we plan for fifteen minutes because rollback is automatic.
Business results are measured before work starts. Conversion rate, task completion and drop-off are tracked the same way before and after launch, for a fair comparison. Each target is agreed with you at kick-off and reviewed at day 90.
Services & packages
Choose what you need built. Each offer lists what is included, the technology we usually use and a typical timeline.
How to buy
How we work with you
Ask a quick question, send a project brief or issue a formal RFQ. The lead for the work reads each one in full, and any services already in your brief go with it.
Or book a thirty-minute call01
For a first conversation, a press request or anything that does not need a scope yet.
You get A reply from a named lead
02Recommended
Goals, audiences, a budget band and timing, so our first reply can outline the work.
You get Options and a first scope after one call
03
Your documents, deadlines and the procurement and security rules the work must meet.
You get Receipt confirmed and a named bid lead
How it is priced
Each package shows its pricing model. Work starts once a written scope and quote are agreed.
Opens a project brief with this package chosen.
In your brief
In your brief
In your brief
In your brief
In your brief
| Package | Every engagement includes | Best for |
|---|---|---|
| SprintA short, fixed-scope engagement that answers one defined question. |
|
Discovery, a diagnostic, a prototype or a decision you need to make soon |
| ProjectA defined scope, delivered for a fixed price. |
|
Work you can describe up front: an identity, a platform or a set of tools |
| MilestoneA larger build in phases you approve and pay for one at a time. |
|
Programmes too large for one contract, where you want control at each step |
| RetainerReserved monthly capacity to run, improve and extend what we built. |
|
Live brands and products that need a steady team without hiring one |
| SquadA dedicated team that works inside your stack and sprint schedule. |
|
Teams with a clear roadmap that need more senior people quickly |
12 · QuestionsSeven questions buyers ask
What buyers ask before a build: platform and CMS choice, code ownership, AI in delivery, support after launch, search rankings and speed.
We recommend one in discovery, based on what the app must do. Deep device integration favours native; shared logic and one team favour Flutter or React Native; many products need only a fast, installable web app. You get the trade-offs in writing.
The one your editors will use. We work with headless options such as Contentful, Sanity, Strapi or WordPress, chosen by content model, editorial workflow, localisation and cost.
What we make for you is yours once it is paid for. Tools we already had stay ours, and you get a free, permanent licence to use them. The code sits in your repositories and cloud accounts from the first commit.
AI drafts code and tests, then gives each change a first review. A named engineer approves every change once automated tests pass. Your code never goes into tools that train on it.
A period of post-launch support, then your choice. Your team takes over with a full handover, or we stay on through Integration & Support with agreed service levels.
Yes, if the migration is planned first. We crawl the current site, map every URL that earns traffic or links and test every redirect. Titles, headings, structured data and internal links are checked on every template. We watch search coverage and impressions daily for a month after launch. Rankings may shift during reindexing, but no URL is dropped by accident.
By making page weight a rule every change must pass. Image, script and font budgets run on every pull request; anything over budget fails before merging. Real-user monitoring tracks Core Web Vitals, and the release guard rolls back any release that slows interactions. At day 90 we review the data with you, fix the three costliest slowdowns and reset the budgets.
You will speak to a lead who would run the work, and get a straight answer on fit.
Three ways to start
Every engagement starts with a written scope and a quote agreed before work begins.
Choose one of the three ways above