Skip to main content

By Denys Kravchenko

Why I build headless Drupal

The short version is plain. Drupal keeps the content, the roles, and the editorial workflow. Next.js keeps the front end. I use that split when the same content has to reach more than one site. If it does not, I stay with a normal Drupal theme.

I have built Drupal sites since 2011. The production build I point people to is El Brujo Online: Drupal 11 as the CMS, JSON:API as the pipe, and a Next.js, React and TypeScript front end. Related brochure sites share that one Drupal codebase. Each front end can look different. The content does not get copied into a second CMS.

Match the architecture to a need

Headless is a tool, not a badge. I go decoupled when the content has to leave one website: a second brochure site, a later app, a kiosk, or some other client that only wants the data. I stay traditional when one site is the whole product and the editors already live in Drupal's theme layer.

If there is only one head, the extra apps are cost. Tokens, CORS, preview, and cache invalidation are real work. They pay off when a second consumer shows up. They do not pay off because React is fashionable.

Drupal is great at content

Content modelling, revisions, roles, multilingual content, and editorial workflows are where Drupal is strong. Editors get a mature admin. I do not rebuild that in the front end.

JSON:API ships in Drupal core. Turn it on and each content type, field, and relationship is an endpoint, with filtering, sorting, and pagination already there. That is the contract the front end codes against. The content stays structured data. The page is one way to show it.

Next.js is great at the front end

Components, TypeScript, and a render model I can cache per route. The front end can ship on its own schedule. Designers and front-end work are not waiting on a theme rebuild for every layout change.

A path on the site resolves to a Drupal node. When an editor publishes, Drupal tells the front end which cache tag to drop, and the next request is fresh. The visitor still gets a fast page. The editor still works in Drupal.

One CMS, many sites

On El Brujo Online, related brochure sites share one Drupal codebase. Content lives in one place. Each front end reads what it needs and renders it in its own components.

How the stack fits togetherContent editors publish in Drupal 10/11. Drupal sends content to Next.js through JSON:API or REST. Figma designs become Storybook components that ship in Next.js. Visitors use the Next.js site. Cypress, Playwright, Jest, and CI check that site.JSON:API / RESTContent editorsDrupal 10/11Figma designsStorybookCypress / Playwright / JestCI/CD, e.g. CircleCINext.js + React + TypeScriptVisitors

What you give up

Traditional DrupalHeadless Drupal 11 and Next.js
One Twig theme, rendered by DrupalA React app you own, cached on its own
Content serves that one websiteThe same content can feed more than one client
Login and preview are built inAuth and draft preview are wiring you add
A PHP and Twig team can run itYou need PHP and TypeScript
One application to deployTwo applications, plus CORS, tokens, and cache rules

The interesting bugs live on the seam. A front end that cannot see unpublished content. A cache that stays warm after an editor hits save. A browser that is allowed to call the API from the wrong origin. I plan for those before I plan for a new component.

When I would not go headless

  • A small site where editors rely on in-place preview and layout tools.
  • A team that cannot own a separate front-end app.
  • A project that must stay on one hosting stack.
  • A single website with no second consumer in sight.

In those cases a traditional Drupal site is simpler and cheaper to run. I would rather ship that than carry two codebases for a brochure.

Want to talk through whether it fits your project?

Written by Denys Kravchenko. Last updated .