Drupal is a powerful content management system (CMS) that provides a robust backend, while Next.js is a fast, modern React framework for building front-end applications. With Next.js 15, the App Router introduces advanced features like caching and improved async handling. This guide will focus on integrating Drupal with Next.js 15 using these new capabilities. π―
π₯ Why Integrate Drupal with Next.js?
- π Decoupled Architecture: Separates the back-end (Drupal) and front-end (Next.js) for increased flexibility.
- β‘ Improved Performance: Next.js 15 introduces automatic caching and async rendering for faster load times.
- π¨ Better User Experience: Provides a modern React-powered front-end for improved interactivity.
- π 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
.
π Basic Project Structure
my-nextjs-app/
βββ app/ # App Router structure
β βββ layout.tsx # Root layout
β βββ page.tsx # Home page
β βββ api/ # API routes
β βββ dashboard/ # Example protected page
βββ components/ # Reusable UI components
βββ styles/ # CSS modules and global styles
βββ public/ # Static assets
βββ package.json # Project dependencies
βββ next.config.js # Next.js configuration
π Setting Up Drupal as a Headless CMS
π Install Drupal (New Setup)
Refer to this guide to set up Drupal locally using 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', 'Authorization']
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 Environment Variables
Create a .env.local
file and add:
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 next.config.ts
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;
π° Fetch Articles from Drupal
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 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>
{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 App Router, you get a powerful, modern, and scalable architecture. π Next.js 15βs improved caching and async capabilities enhance performance, ensuring faster content delivery. With Drupal serving as a robust backend, this setup provides flexibility for managing content while leveraging the interactivity and efficiency of React on the front end. π¨β¨
Top comments (0)