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.