Case Study
A healthcare website rebuilt
for editorial independence.
Migrating GoInvo’s website off aging Gatsby infrastructure and rebuilding it around three things: a Sanity CMS that lets non-technical editors publish independently, an animation layer with card-morph transitions and scroll-driven reveals, and accessibility as a first-class constraint. Live and serving real traffic.
View Project (opens in new tab)The Problem
GoInvo is a healthcare UX studio whose Gatsby site had become a liability on multiple fronts. Build times stretched to minutes as the plugin ecosystem stagnated. Every content update required a developer to write JSX, commit to Git, and wait for a deploy. Accessibility was inconsistent. Animations were absent. The studio’s writers and designers were locked out of their own site.
The brief had three pillars: a CMS that lets editors publish independently: case studies with rich media blocks, vision articles, team bios, job postings; an animation layer that matches the studio’s design quality; and accessibility built into the foundation from the start. The animation work drew on research into how the brain tracks spatial continuity: card-morph transitions maintain object permanence across page changes, reducing the cognitive reorientation cost that hard cuts impose. I wrote migration scripts to port existing content, set up a collaborative editing environment with AI-assisted workflows for incorporating interactive elements and styled explorations from Figma, and built custom components that let the team publish without touching code.

The rebuilt homepage: full-bleed photography, featured case study cards, and a client testimonial ribbon.
Architecture
Content flows from Sanity Studio through GROQ queries into React Server Components, which are statically generated at build time with incremental revalidation for updates. Only interactive elements (animations, forms, the card morph system) hydrate on the client.
Why Next.js 16 App Router: React Server Components eliminate client-side JavaScript for content-heavy pages. Streaming and partial prerendering let the shell load instantly while dynamic content hydrates progressively. Nested layouts made the persistent header/footer with animated page transitions straightforward.
Giving Editors Control
Before: a writer finishes a vision article and sends it to a developer. The developer converts it to JSX, adds images, commits to Git, waits for a build, and deploys. The writer sees the result hours later and asks for three changes. Each round-trip costs a day.
After: the writer opens Sanity Studio, types directly into a rich text editor, drags in images, and sees a live preview of the published page updating as they type. They hit publish. The site updates in seconds. No developer needed.
Getting there meant modeling everything the studio publishes (case studies, articles, team bios, job postings, testimonials, client logos, services, and site-wide settings) as structured Sanity documents. The portable text fields support custom blocks for pull quotes, image grids, and full-bleed sections so editors can create rich layouts without writing markup.
Beyond the schema, I designed the Studio experience itself around how the team actually works. Previews are separated into their own sections so editors see exactly where new content will appear on the live site. Each section includes a blank card with an “Add” button, so a studio member browsing the Vision page can create a new article right there, in the context where it belongs, instead of navigating the Studio’s document list and hoping it lands in the right place. Small UX decisions like these turned the CMS from a content database into a workspace that matches the team’s mental model.

The editor’s view: content on the left, live preview on the right. Changes appear instantly.
Results
0
Dev hours to publish content
9
Content types editors control
0.35s
Page transition duration
AA
WCAG compliance
The site is live and in active use by the studio. Content editors publish case studies, vision articles, and team updates without developer involvement. Pages load with zero client-side JavaScript for static content, hydrating only the interactive layer.

The Vision page on mobile: responsive typography, stacked spotlight cards, and scroll-driven animations adapt gracefully to small screens.
What I'd Do Differently
I stopped treating frameworks as black boxes.
The page transition bug had no Stack Overflow answer. The fix was in React’s internal LayoutRouterContext, which I only found by reading the App Router source. Before this project I would have worked around the limitation. Now I go to the source when docs run out.
I design for production editing patterns now, not developer testing.
Sanity’s live events fired on every keystroke, which was invisible in my single-editor local setup. With three editors in staging, the render storms were immediate. I now stress-test collaborative features with realistic editing behavior from day one.
Small defensive patterns compound across the whole pipeline.
Making the Sanity client return empty arrays when unconfigured (instead of throwing) was a one-line change. It unlocked CI in every environment without CMS credentials and removed an entire class of deployment issues. I think more carefully now about which small decisions have outsized downstream impact.