← All articles

[ Blog ]

June 27, 2026

8 min read

Headless WordPress + Next.js for Animated Sites

How to build award-level animated sites on a headless WordPress + Next.js stack with Three.js and GSAP — architecture, caching, perf budgets and the real trade-offs.

Next.jsWordPressHeadless CMSThree.jsGSAPArchitecture
Headless WordPress + Next.js for Animated Sites

When I launched Iventions — my first collaboration with studio SERIOUS.BUSINESS and designer Huy Phan — the brief demanded two things that usually fight each other: a heavily art-directed, 3D-and-motion front end and a CMS the client's team could edit without calling a developer. The answer was a headless WordPress Next.js stack with Three.js and GSAP. This post is the technical companion to the Iventions case study: how the pieces fit, how I keep a headless CMS for animated websites fast at 60fps, and when this architecture is the right call versus overkill.

A quick note on credit: on Iventions I was the developer. The design and art direction were Huy Phan + SERIOUS.BUSINESS. Everything below is the engineering side of that collaboration.

Why headless WordPress + Next.js at all

The instinct of a lot of creative developers is to reach for a sleek headless CMS (Sanity, Contentful, Payload) and never touch WordPress again. I get it. But on real client projects the deciding factor is rarely developer taste — it's who edits the content after launch. And an enormous number of marketing teams, agencies, and founders already live in WordPress every day.

"Headless" means you keep WordPress purely as a content back end and throw away its PHP theme layer. Editors keep the dashboard, the media library, the roles, and the editorial workflow they already know. Meanwhile users get a custom front end built in Next.js/React — with full control over rendering, animation, and performance that a traditional theme can never give you.

That split is the whole pitch:

  • Editors keep WordPress. Zero retraining, mature roles/permissions, a huge plugin ecosystem for SEO, forms, and custom fields.
  • Users get a fast, bespoke front end. React Server Components, granular caching, code-split WebGL, and a motion system you actually own.
  • The two are decoupled. You can redesign the front end without migrating content, or swap the CMS later without touching the UI layer. That's the "future-proof" part, and it's real, not a buzzword.

How the pieces fit: the architecture

The mental model is a clean pipeline. WordPress is only a content API. Next.js is the entire experience. Three.js and GSAP are presentation layers that the front end owns end-to-end.

WordPress (headless)        Next.js front end            Browser
┌──────────────────┐        ┌────────────────────┐       ┌─────────────┐
│ Posts / pages    │        │ RSC: fetch + cache │       │ React UI    │
│ ACF custom fields│ ──API─▶│ render HTML/JSON   │ ────▶ │ GSAP motion │
│ Media library    │ GraphQL│ revalidate (ISR)   │       │ Three.js 3D │
└──────────────────┘  /REST └────────────────────┘       └─────────────┘

You have two documented ways to read content out of WordPress:

ApproachWhat it isBest when
WPGraphQLA GraphQL endpoint over WP + ACFYou want to fetch exactly the fields a component needs, in one request
WP REST APIBuilt-in /wp-json endpointsYou want zero extra plugins and simple, cacheable URLs

I reach for WPGraphQL on motion-heavy builds because component-driven front ends pair naturally with field-precise queries — a Hero block asks for its headline, its media, and its 3D config in a single round trip, and nothing else. On smaller sites the REST API is perfectly fine and one less moving part.

In the App Router, fetching becomes a server concern, so the WordPress credentials and query weight never reach the browser:

// app/lib/wp.ts — runs only on the server
export async function getPage(slug: string) {
  const res = await fetch(process.env.WP_GRAPHQL_URL!, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      query: /* GraphQL */ `
        query Page($slug: ID!) {
          page(id: $slug, idType: URI) {
            title
            blocks { __typename ...HeroFields ...GalleryFields }
          }
        }`,
      variables: { slug },
    }),
    // ISR: serve cached HTML, refresh in the background every 60s
    next: { revalidate: 60, tags: [`page:${slug}`] },
  })
  if (!res.ok) throw new Error('WP fetch failed')
  return (await res.json()).data.page
}

That next: { revalidate, tags } line is doing the heavy lifting. The Next.js caching docs let you serve a fully static, CDN-cached page while still refreshing content — and a WordPress webhook hitting revalidateTag('page:home') on publish makes edits appear in seconds without a redeploy. That combination is what lets a WordPress-backed site hit the same Core Web Vitals as a fully static one.

The modular, scalable part: blocks map to components

The "modular, scalable, future-proof" line isn't marketing if you model content as blocks and map each block type to one React component. In WordPress you define flexible content (ACF Flexible Content or native Gutenberg blocks); on the front end you render a registry:

const REGISTRY = {
  HeroBlock: Hero,
  GalleryBlock: Gallery,
  Scene3DBlock: Scene3D, // a Three.js section
} as const

export function Blocks({ blocks }: { blocks: Block[] }) {
  return blocks.map((b, i) => {
    const Comp = REGISTRY[b.__typename as keyof typeof REGISTRY]
    return Comp ? <Comp key={i} {...b} /> : null
  })
}

Now editors compose pages from blocks they understand, and every block carries its own motion and 3D config as data. Add a new section type once, and it's available everywhere. This is the same component-driven discipline I describe in the React Three Fiber tutorial for beginners — a 3D scene is just another component that happens to render to a canvas.

Keeping 3D + motion at 60fps over a CMS

A headless setup doesn't make performance free — if anything, 3D and choreographed motion make it harder. My non-negotiables:

  • Animate only transform and opacity. They're GPU-composited and skip layout/paint, leaving the main thread free for scroll and data hydration.
  • Lazy-init WebGL. The Three.js scene mounts only when its section nears the viewport and pauses its render loop off-screen. No GPU cycles burned on what nobody's looking at.
  • Cap the device pixel ratio at Math.min(devicePixelRatio, 2) — above 2 you pay an enormous fill-rate cost for a difference almost no one can perceive.
  • Keep the data on the server. Because RSC fetches and renders WordPress content server-side, the client bundle stays lean and ships closer to interactive faster.
const mm = gsap.matchMedia()
mm.add('(prefers-reduced-motion: no-preference)', () => {
  // full WebGL + GSAP choreography lives here, off by default for reduced-motion users
})

I go deep on the budgets — LCP, INP, CLS under heavy animation — in Core Web Vitals for animation-heavy sites, and on the scroll layer in smooth scroll in Next.js with GSAP & Lenis. The short version: a fast WordPress front end is mostly about not shipping work to the client — cache hard, hydrate little, render motion only when it earns its place.

The hard parts and trade-offs

Headless WordPress is the right tool surprisingly often, but it isn't free. The honest list:

  • Data fetching and caching is the real work. Get revalidate and tag-based invalidation right or you'll either serve stale content or hammer WordPress on every request. This is where most headless builds go wrong.
  • Preview is harder than monolithic WordPress. A draft no longer "just shows up." You need a preview route that fetches uncached, authenticated content via WordPress's preview token — plan for it from day one or editors will be frustrated.
  • You own two systems. WordPress hosting and a Next.js deploy, two sets of updates, two security surfaces. For a tiny brochure site that's overkill — reach for it when there's real editorial volume or a front end too custom for a theme.
  • Plugins assume a theme. Some WordPress plugins inject markup that never reaches a headless front end. Vet your SEO/forms plugins for headless support before committing.

When it's the right call: a content-rich, brand-flagship site with frequent editor updates and an art-directed, animation-heavy front end — exactly Iventions. When it's overkill: a simple site with rare updates, where a static build from Markdown or a lightweight CMS is less to maintain.

Proof it works

Iventions — built on this exact headless WordPress + Next.js + Three.js + GSAP stack — won CSS Design Awards Website of the Month and Awwwards Site of the Day + Developer Award, with the editorial team managing content in WordPress the whole time. The full project story, scores, and craft breakdown are in the Iventions case study, and more shipped work is in the projects archive.

FAQ

Is headless WordPress good for animation-heavy websites?

Yes — it's one of the best fits. WordPress handles content; Next.js owns rendering, so you get full control over GSAP motion and Three.js 3D plus aggressive caching for Core Web Vitals. Editors keep a CMS they know while users get a fully custom front end.

WPGraphQL or the WordPress REST API for Next.js?

Use WPGraphQL when you want field-precise queries per component (ideal for block-based, motion-heavy builds). Use the REST API for simpler sites where one fewer plugin and plain cacheable URLs matter more than query precision.

Does headless WordPress hurt SEO or performance?

No, if you cache correctly. With Next.js ISR (revalidate + tag invalidation) you serve static, CDN-cached HTML and refresh on publish via a webhook — matching the speed of a fully static site while keeping WordPress editing.

When is headless WordPress overkill?

For a small site with rare content changes, running both WordPress and a Next.js deploy is more maintenance than it's worth. Reach for it when there's real editorial volume or a front end too custom and animated for a traditional theme.

Let's build it

If you need a headless WordPress + Next.js site with Three.js and GSAP that your team can edit and that wins on craft, that's exactly what I do as a creative developer.


Written by Hon Tran — creative developer, founder of hontran.dev, and Awwwards jury member. 11+ years building award-winning, performance-first web experiences (Next.js, GSAP, Three.js / WebGL) for clients worldwide. hontran.dev · Behance.