DEV Community

Deepika
Deepika

Posted on

πŸš€ Seamless Headless Drupal Integration with Next.js 15 – Boost Performance!

Image description

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
Enter fullscreen mode Exit fullscreen mode

To start the development server:

npm run dev
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

🌐 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
Enter fullscreen mode Exit fullscreen mode

πŸ”“ 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']
Enter fullscreen mode Exit fullscreen mode

Clear the cache:

ddev drush cr
Enter fullscreen mode Exit fullscreen mode

πŸš€ 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
Enter fullscreen mode Exit fullscreen mode

🌍 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
Enter fullscreen mode Exit fullscreen mode

βš™οΈ 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;
Enter fullscreen mode Exit fullscreen mode

πŸ“° 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;
}
Enter fullscreen mode Exit fullscreen mode

🎨 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>
  );
}
Enter fullscreen mode Exit fullscreen mode

🎯 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. 🎨✨

Image of Quadratic

The native AI interface for your structured data

Simply type in your prompt and generate insights with the latest LLMs and built-in Python functionality.

Try Quadratic free

Top comments (0)

5 Playwright CLI Flags That Will Transform Your Testing Workflow

  • 0:56 --last-failed
  • 2:34 --only-changed
  • 4:27 --repeat-each
  • 5:15 --forbid-only
  • 5:51 --ui --headed --workers 1

Learn how these powerful command-line options can save you time, strengthen your test suite, and streamline your Playwright testing experience. Click on any timestamp above to jump directly to that section in the tutorial!

πŸ‘‹ Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay