 

Drupal JavaScript・4 min read・Posted on June 4, 2025

# Seamless Headless Drupal integration with Next.js 15 (App Router)

 

 

 

 ![Seamless Headless Drupal integration with Next.js 15 (App Router)](/sites/default/files/remediation-media/684055905396cfc5d74a67e8_Seamless_Headless_Drupal_Integration_with_Next.js_15__App_Router_-1__1_.avif) 

 



 

   Table of contents  - [Why integrate Drupal with Next.js?‍](#why-integrate-drupal-with-next-js)
- [Setting up Next.js 15 with App Router](#setting-up-next-js-15-with-app-router)
- [Create a Next.js application](#create-a-next-js-application)
- [Basic Project Structure‍](#basic-project-structure)
- [Setting Up Drupal as a Headless CMS](#setting-up-drupal-as-a-headless-cms)
- [Install and configure Drupal JSON: API](#install-and-configure-drupal-json-api)
- [Enable CORS for API requests](#enable-cors-for-api-requests)
- [Fetching Drupal data in Next.js 15 (Using Async and Cache)](#fetching-drupal-data-in-next-js-15-using-async-and-cache)
- [Conclusion](#conclusion)
 
  

 

**Drupal** is a mature and flexible[ content management system (CMS)](https://www.drupal.org/about) trusted for building structured content models and managing complex workflows.

On the front end, Next.js is a widely adopted React framework known for its speed, developer experience, and production-grade features. With the release of[**Next.js 15**](https://nextjs.org/blog/next-15), the new **App Router** brings powerful updates, including built-in support for async/streaming, granular caching, and improved routing patterns.

When connecting a decoupled Drupal backend to a Next.js 15 frontend, handling authentication becomes a key step, especially for gated content, personalisation, or editorial workflows.

This blog covers how to implement authentication in a headless Drupal + Next.js 15 setup using the latest App Router features and best practices around API routes, sessions, and token handling.

## Why integrate Drupal with Next.js?‍

1. **Decoupled Architecture**: Separates the back-end (Drupal) and front-end (Next.js) for increased flexibility.

1. **Improved Performance**: Next.js 15 introduces automatic caching and async rendering for faster load times.

1. **Better User Experience**: Provides a modern React-powered front-end for improved interactivity.

1. **Scalability**: Using Drupal as a headless CMS makes it easier to scale and manage content across platforms.

## Setting up Next.js 15 with App Router

### Create a Next.js application

Before starting, ensure you have **Node.js** installed. Then, run the following command to create a new Next.js 15 project:  
‍

 ```
npx create-next-app@latest my-nextjs-app --ts --experimental-app
cd my-nextjs-app
npm install
```

‍

To start the development server:  
‍

 ```
npm run dev
```

‍

Your Next.js app should now be running at[ http://localhost:3000](http://localhost:3000/).

### Basic Project Structure‍

 ```
my-nextjs-app/
├── app/                 # App Router directory
│   ├── layout.tsx       # Root layout (applies to all pages)
│   ├── page.tsx         # Home page (/)
│   ├── about/           # Example route: /about
│   │   └── page.tsx
│   └── api/             # API routes
│       └── user/route.ts
│
├── components/          # Reusable components (e.g., Header, Button)
│   └── Header.tsx
│
├── styles/              # Global and module CSS files
│   ├── globals.css
│   └── Home.module.css
│
├── public/              # Static assets (images, favicon, etc.)
│   └── favicon.ico
│
├── next.config.js       # Next.js configuration
├── tsconfig.json        # TypeScript configuration (if using TS)
└── package.json         # Project metadata and dependencies

```

## Setting Up Drupal as a Headless CMS

Install [Drupal new setup](https://drupalize.me/tutorial/install-drupal-locally-ddev)

### Install and configure Drupal JSON: API

To enable API-based communication between Next.js and Drupal, install the **JSON: API** module:  
‍

 ```
ddev composer require drupal/jsonapi
ddev drush en jsonapi -y

```

### Enable CORS for API requests

To allow Next.js to access Drupal’s API, update **services.yml**:  
‍

 ```
cors.config:
  enabled: true
  allowedOrigins: ['*']
  allowedHeaders: ['Content-Type', 'Authorisation']
  allowedMethods: ['GET', 'POST', 'OPTIONS', 'PATCH', 'DELETE']

Clear the cache:
ddev drush cr

```

## Fetching Drupal data in Next.js 15 (Using Async and Cache)

Next.js 15 introduces improved async handling and caching. To fetch content from Drupal, install the required packages:  
‍

 ```
npm install next-drupal drupal-jsonapi-params

```

‍

Set the variables  
‍

 ```
# Required
NEXT_PUBLIC_DRUPAL_BASE_URL=https://my-site.ddev.site/
NEXT_IMAGE_DOMAIN=my-site.ddev.site

NEXT_PUBLIC_BASE_URL=http://localhost:3000

```

‍

Update the image dome in next.config.ts file  
‍

 ```
Import type { NextConfig } from “next”;
const nextConfig: NextConfig = {
 images: {
   domains: ["my-site.ddev.site"], // Allow images from this domain
   remotePatterns: [
     {
       protocol: "https",
       hostname: "my-site.ddev.site",
       pathname: "/sites/default/files/**",
     },
   ],
 },
};

export default nextConfig;
```

Then, create a client to fetch data using the new **fetch API with caching**:  
‍

 ```
import { NextDrupal } from "next-drupal"
import { DrupalJsonApiParams } from "drupal-jsonapi-params";

const drupal = new NextDrupal(process.env.NEXT_PUBLIC_DRUPAL_BASE_URL);

process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; // To fix the development fetch error

export async function fetchArticles() {
 const params = new DrupalJsonApiParams()
   .addFields("node--article", ["title", "id", "body", "field_image", "field_tags"])
   .addInclude(["field_image", "field_tags"])
   .addSort("created", "DESC");

 const response = await drupal.getResourceCollection("node--article", {
   params: params.getQueryObject(),
   cache: "force-cache" // Ensures fast loading
 });
 return response;
}

```

‍

Rendering the fetched content in Next.js 15:  
‍

 ```
import { fetchArticles } from "../lib/drupal";
import Image from "next/image";

export default async function Page() {
 const data = await fetchArticles();
 console.log(data);
  return (
   <div className="">
     {data.map((article) => (
       <div key={article.id || article.title}> {/* ✅ Add key to top-level item */}
         <h2 className="article-title">{article.title}</h2>
        
         {article.field_image?.uri?.url && (
           <Image
             src={`${process.env.NEXT_PUBLIC_DRUPAL_BASE_URL}${article.field_image.uri.url}`}
             alt={article.title}
             width={400}
             height={250}
             className="image"
           />
         )}
        
         {article.body?.value ? <p>{article.body.value}</p> : <p></p>}
        
         {article.field_tags?.length > 0 && (
           <ul>
             {article.field_tags.map((tag, index) => (
               <li key={tag.id || `${tag.name}-${index}`}>{tag.name}</li>
             ))}
           </ul>
         )}
       </div>
     ))}
   </div>
 );
}

```

## Conclusion

By integrating **Drupal’s headless capabilities** with **Next.js 15** and its modern[**App Router**](https://nextjs.org/docs/app/building-your-application/routing), teams gain a powerful architecture that combines content flexibility with frontend performance.

Drupal continues to provide a structured, API-first backend for complex content models and editorial workflows, while Next.js 15 brings faster rendering through granular caching, improved async handling, and enhanced developer ergonomics.

This setup creates a future-ready foundation for scaling digital experiences. You can introduce[](https://www.drupal.org/project/personalize)personalisation, real-time updates, static generation for anonymous content, and even edge rendering with[ Next.js middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware), which also aligns well with the growing demand for composable architectures, enabling easy integration with third-party services like analytics, commerce, or AI-based recommendations.

As headless adoption grows, pairing Drupal with Next.js 15 offers a stable yet forward-looking path, supporting editorial flexibility, high performance, and extensibility for evolving digital products.

‍

‍

 



Written by

Vasantha Deepika

Frontend Engineer

 

Editor

Ananya Rakhecha, Tech Advocate

 

 

 

 

 

 

 ## We'd love to talk about your business objectives

 [ Contact Us  ](/contact)