NEXSUM_LABS
  1. Home
  2. Work
  3. A SaaS analytics vendor rebuilt its docs and marketing surface for interaction speed
Book a call

[ Case study ]

SoftwareNext.js (App Router)React Server ComponentsMDX pipelineWeb Vitals reporting

A SaaS analytics vendor rebuilt its docs and marketing surface for interaction speed

Developers — the buyers — reported the documentation feeling sluggish: code samples re-rendered slowly, search lagged, and tab switches stuttered. Field INP sat at 280ms, and the docs' bounce rate on mobile was the highest of any section.

CLIENT a product-analytics SaaS vendor — FOCUS Isolate the interactive islands

Next.js DevelopmentWeb DevelopmentNext.js DevelopmentSoftwareRepresentative example
Client
a product-analytics SaaS vendor
Industry
Software
Engagement
9 weeks — systems pod — 2 engineers
Service
Web Development / Next.js Development
Headline outcome
p75 INP on docs and marketing pages, 28-day field window after rollout: 280ms → 120ms, read from Web vitals field data

Representative examplesEvery case study in this library is an illustrative composite of the kind of engagement we deliver — written to show our method and standards, not to name clients.

Where they started

Product analytics for engineering teams is this vendor's business, which means the docs are the sales call: developers evaluate the product by reading and poking interactive samples. Docs content lives in Markdown repositories that engineering owns and merges like code; marketing owns the surrounding site; both ship from one deployment. The team could point to every metric that mattered except the one developers actually felt — the docs lagged when you used them.

What it was costing

Developers — the buyers — reported the documentation feeling sluggish: code samples re-rendered slowly, search lagged, and tab switches stuttered. Field INP sat at 280ms, and the docs' bounce rate on mobile was the highest of any section.

What they could see

  • Switching between code samples stuttered visibly, worst on the mobile devices developers actually use.
  • Docs search lagged long enough that people resorted to searching the site's own pages from outside.
  • On real devices the docs lagged visibly at every tap and scroll while lab builds kept showing green.
  • Mobile bounce on the docs ran higher than any other section of the site.

The constraints we worked inside

  • Docs content lived in Markdown repositories owned by engineering; the build could not change their workflow.
  • Interactive code samples were the product's proof — they had to stay, just get fast.
  • The marketing site and docs shared a deployment and had to keep doing so.

What had been tried before

Engineering tightened the build: tree-shaking, lazy routes, and smaller vendor chunks.
The gains evaporated as the sample count grew; each new interactive component reintroduced weight, and nothing stopped the drift.
Docs search was swapped for a hosted third-party widget chosen for speed.
It queried faster but shipped its own bundle and styling, and search interactions were part of the perceived sluggishness, not all of it.

What we proposed

We proposed rebuilding the shared surface on Next.js with strict boundaries: docs pages stream from the server, while code samples and search become isolated client-side islands with per-component bundle splitting. Engineering's Markdown repositories remain the source of truth — the pipeline validates and renders MDX without asking their workflow to change. A per-route bundle budget in CI holds the line, and field Web Vitals monitoring moves onto the release checklist, because the lab demonstrably could not see the problem developers were feeling.

Just as important is what we ruled out, and why:

  • Splitting docs onto a dedicated documentation platformThe shared deployment was a constraint, and a separate pipeline would have split ownership the small team couldn't carry.
  • Replacing interactive samples with static code blocksThe samples are the product's proof; a docs rebuild that removed them would have solved speed by removing the point.
  • Server-rendering everything, islands includedSamples and search need real client interaction; forcing them server-side recreates the lag inside the server queue.

How the work ran

01Isolate the interactive islands

Code samples and search became client-side islands with their bundles split per component; the surrounding pages ship almost no JavaScript.

02Stream the docs tree

Long sidebar and content trees stream server-side, so the first paint carries readable content while the rest resolves.

03Measure INP on real devices

We added field INP monitoring to the release checklist — the lab could not see the problem, so the fix had to be verified where it lived.

Delivered by the systems pod — 2 engineers over 9 weeks, with working increments reviewed with the client every week.

The stack, and the reasoning

Next.js (App Router)
Docs and marketing must keep deploying together; one App Router app with per-route islands honors that constraint instead of fighting it.
React Server Components
The sidebar-and-content tree streams server-side, so first paint carries readable docs while the heavy interactive pieces load where they belong.
MDX pipeline
Engineering's Markdown repos stay the source of truth; the pipeline validates their MDX and renders samples without changing how engineers write or merge.
Web Vitals reporting
Field INP per release is the only honest signal — the lab passed while developers felt lag, so verification had to live where the problem lived.

What went wrong

Obstacle

Engineering's Markdown repositories referenced custom MDX components that no longer existed in the pipeline; the first full build failed across dozens of historical files.

Handled: We added a build-time lint that maps unknown components to fallback renderers and reports them per pull request, so drift gets caught in the repos where it starts.

Obstacle

An aggressive docs caching rule briefly served stale release notes on the marketing side — the shared deployment meant one route's policy could leak into another's.

Handled: We split caching policy per route group, added a deploy smoke check that diffs release-note timestamps, and documented the boundary where future rules belong.

How we worked together

Cadence
Async-first: a written weekly report with per-route vitals, plus a 30-minute call when a decision needed arguing; engineering reviewed everything through pull requests.
Client side
A staff engineer owned the docs repos and reviewed our PRs; the DevRel lead owned content priorities; their CTO joined the architecture decisions.
Decisions
Pipeline and caching decisions were documented as RFCs in their repo and settled in the call when comments disagreed; content stayed DevRel's call.
They provided
Repo access under their review rules, sample-app source for the interactive islands, release-calendar dates to avoid deploy clashes, and field vitals history.

What changed

The headline: p75 inp on docs and marketing pages, 28-day field window after rollout280ms → 120ms, read from Web vitals field data. A second check: docs bounce rate on mobile at −18%.

Developers stopped prefacing demos with an apology for the docs. Code samples respond the way the product does, and engineering stopped treating docs deploys as risk — the shared deployment held. DevRel ships sample updates through the same pull-request flow as product code, so docs work stopped being a favor from engineering and became engineering work. Mobile bounce complaints vanished from the release retro agenda.

The result was read from Web vitals field data against the pre-engagement baseline over the stated window, with a guardrail check on docs bounce rate on mobile. Where platform-reported numbers and business outcomes differ, this record says which layer it is quoting.

What they own now

  • The MDX pipeline in their repository, with the lint rules explaining each fallback.
  • A contribution guide for engineers adding samples without breaking the bundle budget.
  • The per-route vitals reporting, wired into their existing release checklist.
  • Caching policy per route group, documented with the smoke check script.
  • The island component library for code samples and search, versioned alongside docs.

What we would do differently

We would have set an INP budget on the existing site before rebuilding — having the 'before' distribution would have made the win provable per deploy.

Web DevelopmentNext.js DevelopmentSoftwareNext.js (App Router)

Next case study

A nine-school education group went from nine WordPress installs to one admin