TODO - Re-order elements on home page
Next.js 14, Drupal 11 and App Router Support

The future of Drupal is headless

Next.js for Drupal has everything you need to build a next-generation front-end for your Drupal site.

Everything you expect from Drupal.
On a modern stack.

Go headless without compromising features.

Seamless Editing

Inline preview built-in to the editing interface.

Instant Publishing

New content and updates are live instantly.

Multi-site

Power multiple Next.js sites from one Drupal site.

Authentication

Authentication with support for roles and permissions.

Webforms

Built React forms backed by the Webform module.

Search API

Support for decoupled faceted search powered by Search API.

Internationalization

Built-in translation and Automatic Language detection.

Performance

Deploy and scale your sites via content delivery networks.

Security

Protect your site from attacks by separating code from the interface.

Out-of-the-box tooling for the best developer experience

A powerful client for working with JSON:API.

TODO - Update code below for app router
// Create a DrupalClient.
const drupal = new DrupalClient("http://drupal.org", {
    auth: {} // Authentication
    fetcher: {} // Custom fetcher
    cache: {} // Cache support
    serializer: {} // Custom serializer
})
// Fetch an article.
const article = await drupal.getResource(
  "node--article",
  "907034d4-ab35-4949-84e4-d2b7afed82df"
)
// Create an article
const article = await drupal.createResource("node--article", {
  attributes: {
    title: "Title of Article",
    body: {
      value: "<p>Content of body field</p>",
      format: "full_html",
    },
  },
})
// Fetch an article.
const article = await drupal.getResource(
  "node--article",
  "907034d4-ab35-4949-84e4-d2b7afed82df"
)
// Fetch a collection of terms.
const tags = await drupal.getResourceCollection("taxonomy_term--tags")
// Fetch a menu.
const main = await drupal.getMenu("main")
// Fetch a view.
const recentContent = await drupal.getView("content_recent--block")
// Use filters.
const sortedPublishArticles = await drupal.getResourceCollection(
  "node--article",
  {
    params: {
      "filter[status]": "1",
      sorted: "-created",
    },
  }
)
// Create an article.
const article = await drupal.createResource("node--article", {
  attributes: {
    title: "Title of Article",
    body: {
      value: "<p>Content of body field</p>",
      format: "full_html",
    },
  },
})
// Update article.
const article = await drupal.updateResource(
  "node--article",
  "a937dd34-5407-4fff-8594-fccaaa5bb72a",
  {
    data: {
      attributes: {
        title: "Title of Article",
      },
    },
  }
)
// Delete article.
const deleted = await drupal.deleteResource(
  "node--article",
  "a937dd34-5407-4fff-8594-fccaaa5bb72a"
)
// Get the `es` translation for a page by uuid.
const page = await drupal.getResource(
  "node--page",
  "07464e9f-9221-4a4f-b7f2-01389408e6c8",
  {
    locale: "es",
    defaultLocale: "en",
  }
)
// Fetch a collection of translated articles.
const articles = await drupal.getResourceCollection("node--article", {
  locale: "es",
  defaultLocale: "en",
})
// Fetch translated menu items.
const main = await drupal.getMenu("main", {
  locale: "es",
  defaultLocale: "en",
})
// Bearer token.
export const drupal = new DrupalClient(
  process.env.NEXT_PUBLIC_DRUPAL_BASE_URL,
  {
    auth: {
      clientId: process.env.DRUPAL_CLIENT_ID,
      clientSecret: process.env.DRUPAL_CLIENT_SECRET,
    },
  }
)
// Basic.
export const drupal = new DrupalClient(
  process.env.NEXT_PUBLIC_DRUPAL_BASE_URL,
  {
    auth: {
      username: process.env.DRUPAL_USERNAME,
      password: process.env.DRUPAL_PASSWORD,
    },
  }
)
// Bring your own.
export const drupal = new DrupalClient(
  process.env.NEXT_PUBLIC_DRUPAL_BASE_URL,
  {
    auth: () => {
      // Do something and return an Authorization header.
    },
  }
)
// DrupalNode
const article = await drupal.getResource<DrupalNode>(
  "node--article",
  "907034d4-ab35-4949-84e4-d2b7afed82df"
)
// DrupalTaxonomyTerm
const tags = await drupal.getResourceCollection<DrupalTaxonomyTerm[]>(
  "taxonomy_term--tags"
)
// Any resource type.
const resources =
  await drupal.getResourceCollection<JsonApiResource[]>("entity--bundle")
const data = await query({
  query: `
      query {
        nodeArticles(first: 10) {
          nodes {
            id
            title
            path
            author {
              displayName
            }
            body {
              processed
            }
            created
            image {
              width
              url
              height
            }
          }
        }
      }
    `,
})