One design system.
A studio that can publish.

GoInvo’s website connects a shared design system with a CMS the studio can use without developer handoffs. I have led the rebuild since February 2026, working alongside colleagues on content, brand consistency and publishing workflows, and I built checks to keep changes reliable across pages. With studio leadership, I also turned marketing proposals into experiments and made first-party storage their source of record.

Designing with the studio

On the old Gatsby site, routine content updates meant writing JSX, committing code and deploying. Styles and interactions varied by page. Rebuilding the stack alone would have left those problems intact.

I talked with designers across the studio about what they needed a CMS to let them do, then built it on Sanity.io. Years of articles had formatted the same elements differently, with titles, paragraphs and media styled page by page, so I unified them into one design system for components, headers, typography and columns, and mapped those patterns to reusable Sanity blocks.

Writers can now edit text and images beside a live preview, choose layouts and publish without requesting a custom page. Shared patterns keep that flexibility from turning into one-off styling.

I kept editorial content in structured Sanity blocks and page presentation in shared Next.js components. Content changes trigger targeted revalidation, so publishing one page doesn’t rebuild unrelated ones.

Sanity Studio showing side-by-side live preview and content editing for a case study
Sanity Studio: live preview on the left, content editor on the right.

Verifying the whole migration

AI-assisted changes exposed a recurring failure: fixing a shared component on one page could break it on another. Some pages were also only partly migrated even when the work was reported as complete.

I set up regression checks around those failures. With styles and components unified, the same rules applied across pages, and cross-page checks showed when a fix in one place changed something elsewhere. I used Puppeteer and parsed page structures into trees to compare old and new pages, and I reviewed parity from those checks rather than from an AI report that the pages matched. A page-by-page task list separated finished pages from partial migrations and kept the whole site in scope while components and routes were changing.

Experiments and marketing tools

With studio leadership, I translated marketing proposals into experiments with a primary outcome, diagnostic signals and a decision window. For example, a booked conversation is an outcome, and a click on a work page is a diagnostic signal that helps explain behavior.

The Vercel Flags SDK assigns each visitor a stable variant from precomputed pages. A first-party beacon records exposures and conversions through Vercel KV into Sanity, which is the source of record; events are forwarded to GA4 server-side through the Measurement Protocol, alongside Vercel Web Analytics and Speed Insights. Minimum-event floors keep inconsistent tracking or small samples from deciding a winner. So far I’ve verified that these events are captured correctly. I’m not claiming a conversion or revenue lift, and GoInvo’s audience analytics stay private.

I connected campaigns, channels and funnels to their measurement sources, so the team can fix a measurement gap before judging performance. Marqueta, the studio’s LLM marketing assistant, drafts briefs from rough updates for someone to review, and the shared desk keeps the work Marqueta can prepare separate from the decisions a person has to make.

Marqueta’s figures come from GROQ queries over Sanity records, never from the model. Writes use deterministic document IDs and optimistic revision locks, so a retried Slack event cannot post twice, and a scheduled run that succeeds but changes nothing is reported as a failure rather than a success.

The dashboard flags a campaign with no analytics source and names the next setup step.

GoInvo Analytics Dashboard showing connected sources, measurement coverage and a campaign that needs an analytics source

Actual CMS interfaces with illustrative data. Marqueta’s response is simulated.

Publishing without handoffs

Since the June 2026 launch, editors have published case studies, articles and team updates without developer involvement. I wrote the CMS handbook, and a teammate has shipped through the same release pipeline.

Measured against the last Gatsby version, Lighthouse accessibility rose from 77–87 to 96–100, SEO from 86 to 100, and homepage images from 31 MB to 0.5 MB. In a later change I raised the homepage’s mobile performance score from 48 to between 62 and 92 across runs by finding content that stayed hidden until JavaScript ran and deferring third-party scripts. A CI check flags any deploy that regresses it, and accessibility is covered by axe-core audits, ARIA labelling and cross-device testing.

GoInvo homepage showing hero section, featured case study, and client testimonial
Shared type, layout and content patterns on the rebuilt homepage.
Architecture and interaction demo

Next.js 16, React 19 and TypeScript render Sanity content queried with GROQ. Debounced revalidation avoids repeated preview renders during concurrent editing. Release checks cover accessibility, SEO, publishing, webhooks and measurement.

A FrozenRouter adapter retains the outgoing page until its transition finishes, and regression tests cover navigation.

Category filtering on Work, followed by transitions between the main site pages.
GoInvo Vision page on mobile showing responsive layout with spotlight cards and featured articles
The Vision page on mobile.

I owned product direction, architecture, review, testing, and release. Claude Code and Codex implemented changes under my direction and review.