# next-drupal and the plumbing of a decoupled Drupal front end

> next-drupal is a TypeScript client library that gives Next.js applications a typed way to talk to Drupal over JSON:API or GraphQL, with helpers for authentication, webforms, search, i18n and preview. The catch is that it is a monorepo with a large surface, and the value of the library depends heavily on how your Drupal site is configured.

**chapter-three/next-drupal** — Next.js for Drupal has everything you need to build a next-generation front-end for your Drupal site: SSG, SSR, and ISR, Multi-site, Authentication, Webforms, Search API, I18n and Preview mode (works with JSON:API and GraphQL).

- Repository: https://github.com/chapter-three/next-drupal
- Website: https://next-drupal.org
- Stars: 711 · Forks: 216
- Language: TypeScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/chapter-three-next-drupal

## A client library, not a starter kit

Next.js for Drupal is presented as a next-generation front end for a Drupal site, and the README lists what it gives you: SSG, SSR and ISR, multi-site, authentication, webforms, Search API, i18n and preview mode, working with both JSON:API and GraphQL.

The important word is library. This is not a site generator or a template that produces a finished front end for you. It is the layer that handles talking to Drupal, and it leaves the decisions about pages, routing and components to you.

That framing matters for evaluating it. A team that has already decided on a decoupled setup can drop the library into an existing Next.js app and get the Drupal-specific plumbing in one place. A team still deciding whether to decouple will find the library answers a question it has not asked yet.

Development is sponsored by Chapter Three, and the project publishes a live demo at demo.next-drupal.org alongside its documentation site. The repository is organised as a monorepo with packages, examples, starters, a drupal directory, a www directory for the docs site, and a modules directory that holds the Drupal side.

## The example that shows the shape of the API

The README's example is a page listing all Article nodes, and it is short enough to read in full, which is the best introduction to the design.

A NextDrupal instance is created with the base URL of the Drupal site:

```jsx
import { NextDrupal } from "next-drupal"
const drupal = new NextDrupal("https://cms.next-drupal.org")
```

The component receives its data as a prop rather than fetching it itself, which is the shape Next.js expects for static generation. The data comes from getStaticProps, and the library provides a helper that takes the resource type and the Next.js context:

```jsx
export async function getStaticProps(context) {
  const articles = await drupal.getResourceCollectionFromContext(
    "node--article",
    context
  )

  return {
    props: {
      articles,
    },
  }
}
```

Two details are worth noticing. The resource type is a Drupal JSON:API resource identifier, node--article, not a REST path, so the library is speaking JSON:API rather than emulating Drupal's core REST endpoints. And the FromContext naming is doing real work: it is the piece that knows how to turn a Next.js request context into the right Drupal request, which is what makes preview mode and multi-site possible in the first place.

The GraphQL route is the alternative to all of this, and there is a dedicated example for it in the repository's examples directory.

## Two module directories and a sync script for each

The monorepo structure tells you that this project maintains code on both sides of the decoupling.

There is a drupal directory that is a full Drupal installation used for development and testing, and a modules directory that holds the Drupal modules for the next_drupal project. The package.json runs the PHP side through PHPUnit with an in-memory SQLite database, and the phpcs script lints the modules against a standard in modules/next/phpcs.xml.

The sync scripts show how the two halves are distributed. sync:modules runs a shell script that pulls modules from git.drupal.org into modules/*, and sync:examples and sync:starters pull examples and starters from separate GitHub repositories. The starter releases are synced from a canary branch as well as main.

This is an unusual arrangement and it is worth understanding before adopting, because it means the library and the Drupal modules move on different schedules and live in different places. A Drupal developer installs the next Drupal module from the Drupal.org project, and a frontend developer installs the npm package. The monorepo is where both are developed together, not where a consumer installs from.

The examples directory shows how much surface the library covers, with separate examples for authentication, blog, client, custom auth, custom cache, custom fetcher, custom serializer, GraphQL, marketing, router migration, search API, umami and webforms. Each of those is a working configuration you can read.

## Preview mode, multi-site and i18n need configuration on both ends

Several of the headline features are not things the client library can do alone, and this is where most of the evaluation effort should go.

Preview mode requires that the Drupal side can render a preview of unpublished content and hand back a token that the Next.js application can present on a subsequent request. The library provides the client mechanics, but the Drupal module and the site's preview configuration have to exist.

Multi-site has the same shape. A NextDrupal instance is created with a base URL, and multi-site means several of those against several Drupal instances, which means the front end needs a way to decide which site a request belongs to and the deployment needs the credentials for each.

Internationalisation is described in the list of supported features, and the underlying mechanism is Drupal's own language negotiation, which the request context has to carry through.

The customisation examples in the repository are the practical guide here. There is a custom cache example, a custom fetcher example, a custom serializer example and a custom auth example, which is a clear signal of what the library expects you to override. If your project needs to change how responses are cached, how requests are signed, or how a response is turned into a typed object, that is where you will be writing code, and the examples show the extension points rather than leaving you to guess them.

## Tooling, releases and the state of the repository

The repository is not archived and the last push was on 2026-09-23. There are no GitHub releases, and the release process is visible in the files at the root instead: a release-please-config.json with a matching release-please-manifest.json, a CHANGELOG.md, MAINTAINING.md, and a commitlint configuration.

The tooling is a mix of old and new. The package manager is yarn at 1.22.15 and the workspaces are declared in package.json, while the task runner is turbo, with turbo.json at the root and lerna.json for the older per-package commands. The dev script is turbo run dev --parallel, and the end-to-end tests run through turbo as well. There is a husky directory with a lint-staged configuration, and linting is eslint with a .eslintrc.json, formatting is prettier, and the TypeScript config is at the root.

There is also a CI script set that separates macOS and Windows, since the project has to build and test on both. A seed script creates test content with NUM_NODES=200 node ./scripts/seed, and a Cypress-style browser test target exists for the end-to-end runs.

The licence is MIT and the repository carries a SECURITY.md alongside the contributing guidelines and a separate TESTING.md.

The practical upgrade question is therefore about versions rather than tags. With release-please managing changelog and version bumps from conventional commits, and with no GitHub releases to pin, a consumer following a canary branch is following something that changes without a release event.

## Conclusion

next-drupal is a good fit for a Drupal shop that has decided to keep Drupal as the content backend while moving presentation to Next.js, because the library covers the parts of that split that are tedious to write, namely authentication, preview and the JSON:API or GraphQL request layer. It is a poor fit for a team that has not yet decided on decoupled architecture, since the setup work on the Drupal side is the larger part of the project, and a poor fit if you only need to read a handful of nodes. Before adopting, check which Drupal modules you depend on for the features you want, because the repository description names the capabilities but the individual integrations are implemented as separate Drupal modules, and confirm the maintenance path, since the repository has no GitHub releases and the last push was on 2026-09-23.

## FAQ

### What is next-drupal and what does it give a Next.js project?

It is a TypeScript library for building a next-generation front end for a Drupal site, providing SSG, SSR and ISR, multi-site, authentication, webforms, Search API, i18n and preview mode, and it works with both JSON:API and GraphQL.

### How do I fetch Drupal content in next-drupal?

Create a NextDrupal instance with the base URL of the Drupal site, then call a helper such as getResourceCollectionFromContext with a resource type like node--article and the Next.js context, returning the result as props from getStaticProps or a similar function.

### Does next-drupal include Drupal modules as well as the TypeScript library?

The project maintains both sides. The monorepo holds a drupal directory used for development and testing, a modules directory with the Drupal modules for the next_drupal project, and scripts that sync modules, examples and starters from their upstream repositories.

### How do I customise how next-drupal fetches or serialises data?

The repository ships examples for custom cache, custom fetcher, custom serializer and custom auth configurations, which are the extension points for overriding how requests are made and how responses are turned into typed objects.

## Sources

- [chapter-three/next-drupal on GitHub](https://github.com/chapter-three/next-drupal)
- [Issues](https://github.com/chapter-three/next-drupal/issues)
- [License: MIT](https://github.com/chapter-three/next-drupal/blob/main/LICENSE)
- [Project website](https://next-drupal.org)
- [README](https://github.com/chapter-three/next-drupal/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/chapter-three-next-drupal
