Templating Content

Package versions

These docs use the following package versions:

  • prismic-reactjs: v1.3
  • @prismicio/client: v5

The docs will soon be updated to use the latest versions of these packages. If you wish to use the latest versions today, you can update your project by following the migration guides for each package.

On this page, you'll learn how to template content from the Prismic API in your Next.js application.

🕙 Before Reading

This article assumes that you have queried your API and saved the document object in a variable named document.

Simple content fields

These are simple content fields which you just need to render with their API ID. These are represented as either a string, a number, a category, or a boolean. Templating them is quite simple.





Key Text








Here's a simple example of how to template the Number field value from its API ID. As mentioned in the above table, the Number field API ID is example_number. Just like this, you need to retrieve other fields in the table.

<span>{ document.data.example_number }</span>

Structured content fields

The remaining structured content types are:

  • Date
  • Timestamp
  • Geopoint
  • Embed
  • Group

Date and Timestamp

The raw response of these fields provides the following formats:

  • Date: YYYY-MM-DD
  • Timestamp: YYYY-MM-DDTHH:MM:SS+0000







Here's an example of how to retrieve the Date object and Timestamp object from a Date field and Timestamp field using the prismic-reactjs Date method. And convert them to a String using a toString method.

  • Date
  • Timestamp
import { Date } from 'prismic-reactjs'

const exampleDate = Date(document.data.example_date).toString;
// Date outputs as "2020-12-12" 
import { Date } from 'prismic-reactjs';

const eventDate = Date(document.data.event_date).toString;
// Timestamp outputs as "2020-12-12T06:00:00+0000"

Format the Date and Timestamp field

To format these fields, you can choose one of these options:

  1. Use a library such as date-fns-tz.
  2. The built-in DateTimeFormat method.

Here's an example of how to convert the Date or Timestamp object to a formatted string using date-fns-tz:

  • Date
  • Timestamp
import { Date } from 'prismic-reactjs';
import { format } from 'date-fns-tz'

const date = Date(document.data.example_date)
const displayDate = format(date),'MMMM dd, yyyy');
// Outputs as "December 12, 2020 
import { Date } from 'prismic-reactjs';
import { format } from 'date-fns-tz'

const eventDate = Date(document.data.event_date)
const formatedTimestamp = format(eventDate,'MMMM dd, yyyy H:mm a');
// Outputs as "December 12, 2020 12:00 PM"

The built-in DateTimeFormat method :

  • Date
  • Timestamp
import { Date } from 'prismic-reactjs';

const date = Date(document.data.example_date);

const formattedDate = Intl.DateTimeFormat('en-US',{
  year: 'numeric',
  month: 'short',
  day: '2-digit' }).format(date);
// Output in M d, Y format
import { Date } from 'prismic-reactjs';

const timestamp = Date(document.data.event_date);

const formattedTimestamp = Intl.DateTimeFormat('en-US',{
  year: "numeric",
  month: "short",
  day: "2-digit",
  hour: "numeric",
  minute: "2-digit",
  second: "2-digit"
// Outputs the date and time in Mon dd, YYYY, H:MM:SS AM/PM format


Here is an example of how to retrieve the latitude & longitude coordinates for a GeoPoint field. In this case, the API ID for the GeoPoint field is location.

const location = document.data.location;
const lat = location.latitude;  // latitude
const long = location.longitude; // longitude


This is the API response of the Embed field.

"embed_video": {
  "version": "1.0",
  "url": "https://prismic.io",
  "type": "link",
  "title": "Make your website editable for the whole team - Prismic",
  "provider_name": null,
  "thumbnail_url": "https://images.prismic.io/prismic-website/6e49007fec52f99861047cdd55b3ab190ea04295_dev-landing-page-image.png?auto=compress,format",
  "html": "<div data-type=\"unknown\"><a href=\"https://prismic.io\"><h1>Make your website editable for the whole team - Prismic</h1>
  "embed_url": "https://prismic.io/"

You can template an Embed field using the html from the response. In case, the API ID for the Embed field is embed_video.

// In a React component
render () {
  return <div dangerouslySetInnerHTML={{ __html: document.data.embed_video.html }} />


In Prismic, you can define an image's alt text, copyright, and alternate crops — all of which can also have their own alt text. All of this information is served in the API response. An Image field might look like this:

// document.data.example_image
  dimensions: {
    width: 1920,
    height: 1302
  alt: null,
  copyright: null,
  url: "https://images.prismic.io/sm-20201204-2/7d1fba99-5bec-4d59-b8eb-402706e2d36c_a-pril-62u95KgB49w-unsplash.jpg?auto=compress,format"

You can template an image with the img element:

<img src={document.data.example_image.url} alt={document.data.example_image.alt} />

Rich Text and Titles

Rich Text and Titles are delivered in an array that contains information about the text structure. Here's an example of the API response of the Rich Text field (Title fields follow the same format):

// document.data.example_rich_text
    type: "paragraph",
    text: "Example Rich Text Value",
    spans: [
        start: 8,
        end: 17,
        type: "strong"

Rich Text component

Here's how to render Rich Text or a Title with the Rich text component:

<RichText render={document.data.example_rich_text} linkResolver={linkResolver} />

Rich Text helper function

The basic usage of the Rich Text / Title field is to use the RichText.render method to transform the field into HTML code.

{RichText.render(document.data.rich_text_example, linkResolver)}

Plaintext helper function

If a developer wants complete control of the style(CSS), the RichText.asText method will be useful because it converts and outputs the text as a string. Here is how to get plain text from a Rich Text or Title field with the plaintext helper function:



The group allows you to create repeatable content templates. Group fields are available in the main section of your document. A Group field renders an array of content groups:

// document.data.example_group
    example_boolean_in_group: true,
    example_number_in_group: 3,
    example_key_text_in_group: "dog"
    example_boolean_in_group: false,
    example_number_in_group: 7,
    example_key_text_in_group: "cat"

To template a Group, you can use a map function map():

  {document.data.example_group.map((post, i) => (
    <li key={`post-${i}`}>


You can add any of the above fields in reusable content models called Slices, learn more about Slices. The best practice for working with Slices that contain these fields is to create reusable components and pass down the data as props.

In the text Slice below, the entire Slice data is passed down as a prop named slice. Then the text field, which is in the non-repeatable zone (primary), is templated using its API ID of text.

import React from 'react'
import { RichText } from 'prismic-reactjs'

 * Text slice component
const Text = ({ slice }) => (
  <div className="container">
    <RichText render={slice.primary.text} />

export default Text

Render Slices with the SliceZone

The next-slicezone package provides a component to which you pass Slice data, it then matches them with front-end components.

Install this package with the command below:

  • npm
  • Yarn
npm i next-slicezone
yarn add next-slicezone

To use the SliceZone component you will need to pass it 2 props:

  1. slices: This is the Slice content data coming from the Prismic API.
  2. resolver: This is where you pass the local location of your Slices components.

In the example below the SliceZone is imported from the next-slicezone package and used inside a page component.

All the local Slice components are imported into the page using the variable Slices, they are exported from an index.js file in a local 'Slices' folder (example in the 2nd tab below). The index.js file is maintained by Slice Machine, if you aren't using it you will have to maintain this file yourself. Then pass this Slices variable to the resolver prop escaping each Slice.

Then the page content is queried from Prismic and just the Slices content is passed to the SliceZone. In the example, it's passed as slices={page.data.body}.

Your Slices object maybe page.data.slices, check this in your API Browser to be sure.

  • [uid].js
  • ~/slices/index.js
// Truncated Page example using SliceZone

import React from 'react'
import { Client } from '../utils/prismicHelpers.js' // Initialise client import for querying
import SliceZone from 'next-slicezone'
import * as Slices from '../slices' // index.js import from the slices folder, this folder name is arbitrary

 * Post page component
const Page = ({ page }) => {
  if (page && page.data) {
    return (
        resolver={({ sliceName }) => Slices[sliceName]}

  return null

export async function getStaticProps({ params }) {
  const page = (await Client().getByUID('page', params.uid)) || {}
  return {
    props: {
      page, // Prismic document data is returned as the variable page

export default Page
// These are example Slice names only

export { default as BannerSlice } from './BannerSlice'
export { default as FeaturedImage } from './FeaturedImage'
export { default as FullWidthImage } from './FullWidthImage'
export { default as ImageGallery } from './ImageGallery'
export { default as QuoteSlice } from './QuoteSlice'
export { default as TextSlice } from './TextSlice'

💡 Further Learning: Content Types You can learn more about all of these content types in our Content Modeling documentation.

Related articles:

Was this article helpful?
Not really
Yes, Thanks

Can't find what you're looking for? Get in touch with us on our Community Forum.