Building Pages
How to build pages using JSON:API resources from Drupal.
In Next.js V14, data fetching has evolved significantly from previous versions. Instead of using getStaticProps and getServerSideProps you now use the native fetch function enhanced by Next.js to handle server-side data fetching.
The NextDrupal client provides several functions to help you query JSON:API resources from Drupal.
Basic Example
Here's an example which uses getResource to fetch a page node by ID:
const node = await drupal.getResource( "node--page", "07464e9f-9221-4a4f-b7f2-01389408e6c8")A full page would look like this:
app/about/page.tsx
// page will be generated at build timeexport default function AboutPage() { // Fetch the node from Drupal. const node = await drupal.getResource( "node--page", "07464e9f-9221-4a4f-b7f2-01389408e6c8" )
return ( <article> <h1>{node.title}</h1> // ... </article> )}Dynamic pages
You can use Next.js dynamic routes to build static pages for Drupal entity types.
Start by creating a page at /app/[...slug]/page.tsx, where [...slug] maps to the path alias for an entity type (or content type) in Drupal.
This means /app/[...slug]/page.tsx will handle all pages with the following aliases: /about, /team, /another/path ...etc.
To build static pages, there is a built-in function we need to use:
generateStaticParams: to tell Next.js all the routes that we want to have pre-rendered at build time.
app/[...slug]/page.tsx
export async function generateStaticParams() { // Build paths for all `node--page`. const resources = await drupal.getResourceCollectionPathSegments( "node--page" ); return resources.map((resource) => slug: resource.segments);}export default function Page({ params }) { const {slug} = params;
// Construct drupal path based on params const drupalPath = drupal.constructPathFromSegment(slug)
// Fetch the node based on drupal path. const node = drupal.getResourceByPath(drupalPath)
return ( <article> <h1>{node.title}</h1> // ... </article> )}Advanced Example
In the example above, we used app/[...slug]/page.tsx to build static pages for node--page.
We can go a step further and handle all node types (or any entity types) in one page.
To do that, we're going to use translatePath which returns info about the resource type based on slug value in params.
Let's update app/[...slug]/page.tsx to handle both node--page and node--article.
app/[...slug]/page.tsx
import { DrupalJsonApiParams } from "drupal-jsonapi-params"
export async function generateStaticParams() { // Build paths for all `node--page` and `node--article`.
const resources = await drupal.getResourceCollectionPathSegments( ["node--page", "node--article"] ); return resources.map((resource) => slug: resource.segments);}
export default function Page({ params }) { const {slug} = params;
const path = drupal.translatePath(slug)
// Get the resource type. const type = path.jsonapi.resourceName
const params = new DrupalJsonApiParams()
// Fetch the title, path and body field for pages. if (type === "node--page") { params.addFields("node--page", ["title", "path", "body"]) }
// Fetch additional fields for articles. if (type === "node--article") { params.addFields("node--article", ["title", "path", "body", "uid"]) }
const node = await drupal.getResource(path, path.entity.uuid { params: params.getQueryObject(), })
// Render different Components based on Node type. if (node.type === "node--page") { return <PageComponent node={node}/> }
if (node.type === "node--article") { return <ArticleComponent node={node}/> }
return null}Reference
See the fetching JSON:API resources section for more examples of fetching resources and collection of resources.
Pages Router
TODO