Query Content from the CMS

To work with your content in Next, you must first query it from the Prismic API. On this page, you'll learn how to do a Prismic API query in your Next project.


Define an API client endpoint

Before querying documents from your repository, define a Client variable that refers to the instantiated @prismicio/client library with the API endpoint of your repository. If you are working with any of our sample projects, this variable is already setup.

In the following example we create and instance of the API client in a ~/prismic-config.js file

Copy
const Prismic = require('@prismicio/client');

// Update your-repo-name with the name of your repository.
const apiEndpoint = 'https://your-repo-name.cdn.prismic.io/api/v2'
const Client = Prismic.client(apiEndpoint, { req })

After configuring your Client, now you'll be able to create queries. There are two main ways to query the Prismic API:

  • With next-slicezone
  • With @prismicio/client

Below, we'll go through each of those methods in detail.

Should I use next-slicezone or the @prismicio/client library?

If your project makes good use of Slices and Slice Machine, then use next-slicezone.

Otherwise, if:

  • You want to make more advanced queries,
  • You want to query menus, headers, or footers,
  • You want to query content outside of the Slice Zone,

then, the @prismicio/client library will be more efficient.

Query with next-slicezone

next-slicezone provides two lifecycle hooks. useGetStaticPaths(), which determines the routes for the pages, and useGetStaticProps() which gets the data for those pages, as well as a <SliceZone /> component that returns slices found and matches them with front-end components.

next-slicezone version

The following examples use the latest version of the next-slicezone package (0.1.0-alpha.0), which changes how values from the parameters are called. Learn more about next-slicezone's Lifecycle hooks.

To install this run npm install next-slicezone@0.1.0-alpha.0

Query Singleton types

To query a Single type document, declare the queryType as 'single' inside the useGetStaticProps method and declare the name of the type; in this example is called 'homepage'. The function does the query for us, and we pass the Slices and Route Resolver as props to the <SliceZone /> component:

Copy
// Example 〜/pages/index.js file

// Update the path for your API client file.
import { Client } from '../path-to-your-API-client-config'
import SliceZone from 'next-slicezone'
import { useGetStaticProps } from 'next-slicezone/hooks'

// Update the path for your route resolver file.
import resolver from '../path-to-your-resolver-config'

const Page = ({ slices }) => <SliceZone slices={slices} resolver={resolver} />

// Fetch content from prismic
export const getStaticProps = useGetStaticProps({
  client: Client(),
  queryType: ‘single’,
  type: ‘homepage’
})

export default Page

Query Repeatable types by UID

To query a Repeatable type document by UID, inside the useGetStaticPaths pass the uid in formatPath. In the useGetStaticProps method, retrieve the uid from the params are passed by getStaticPaths. The function does the query for us; then, we pass the Slices and Route Resolver as props to the <SliceZone /> component:

Copy
// Example 〜/pages/contact.js file

// Update the path for your API client file.
import { Client } from '../path-to-your-API-client-config'
import SliceZone from 'next-slicezone'
import { useGetStaticProps } from 'next-slicezone/hooks'

// Update the path for your route resolver file.
import resolver from '../path-to-your-resolver-config'

const Post = ({ slices }) => <SliceZone slices={slices} resolver={resolver} />

// Fetch content from prismic
export const getStaticProps = useGetStaticProps({
  client: Client(),
  type: 'post',
  apiParams({ params }) {
    // params are passed by getStaticPaths
    return {
      uid: params.uid,
    }
  },
})

// fetch all docs of type `MyPage` and pass params accordingly
export const getStaticPaths = useGetStaticPaths({
  client: Client(),
  type: 'post',
  formatPath: (prismicDocument) => {
    return {
      params: {
        uid: 'contact-us',
      },
    }
  },
})

export default Post

Query Repeatable types dynamically

Next.js generates dynamic routes for files with names wrapped in brackets, such as [uid].js. Then, queries are done for us in the next-slicezone/hooks and we pass the Slices and Route Resolver as props to the <SliceZone /> component. See the dynamic apiParams variable in useGetStaticProps, and the formatPath in useGetStaticPaths.

Copy
// Example 〜/pages/[uid].js file

// Update the path for your API client file.
import { Client } from '../path-to-your-API-client-config'
import SliceZone from 'next-slicezone'
import { useGetStaticProps, useGetStaticPaths } from 'next-slicezone/hooks'

// Update the path for your route resolver file.
import resolver from '../path-to-your-resolver-config'

const Page = ({ slices }) => <SliceZone slices={slices} resolver={resolver} />

export const getStaticProps = useGetStaticProps({
  client: Client(),
  apiParams({ params }) {
    return {
      uid: params.uid,
    }
  },
})

export const getStaticPaths = useGetStaticPaths({
  client: Client(),
  formatPath: (prismicDocument) => {
    return {
      params: {
        uid: prismicDocument.uid,
      },
    }
  },
})

export default Page

Static Generation with Next.js

next-slicezone's lifecycle hooks were created as an extended functionality of Next.js' getStaticQuery and getStaticPaths. Refer to Next's Official documentation to learn more about how these methods work.

Query outside of the SliceZone

useGetStaticProps automatically queries top-level content fields from your documents, this is considered data outside of the Slice zone. You'll be able to see this data when accessing the props. In this example, we use the data to render a Rich Text field with the API of title using the prismic-reactjs library:

Copy
// Example 〜/pages/[uid].js file

// Update the path for your API client file.
import { Client } from '../path-to-your-API-client-config'
import { RichText } from 'prismic-reactjs'
import SliceZone from 'next-slicezone'
import { useGetStaticProps, useGetStaticPaths } from 'next-slicezone/hooks'

// Update the path for your route resolver file.
import resolver from '../path-to-your-resolver-config'

const Page = ({ slices, data }) => {
  return (
    <>
      {RichText.render(data.title)}
      <SliceZone resolver={resolver} slices={slices} />
    </>
  )
}

export const getStaticProps = useGetStaticProps({
  client: Client(),
  apiParams({ params }) {
    return {
      uid: params.uid,
    }
  },
})

export const getStaticPaths = useGetStaticPaths({
  client: Client(),
  formatPath: (prismicDocument) => {
    return {
      params: {
        uid: prismicDocument.uid,
      },
    }
  },
})

export default Page

Query with @prismicio/client

The @prismicio/client library contains Helper functions to query and render content from the Prismic API. Here are the most commonly-used query helper functions and use cases:

Query Singleton

Queries the API for the document of a given singleton Custom Type. type refers to the API ID of the document's custom type.

Copy
// Update the path for your API client file.
import { Client } from '../path-to-your-API-client-config'

// Syntax: getSingle(custom-type)
const document = await Client().getSingle('homepage')

Query by UID

Queries the API for the document of a given type with a given UID. type refers to the API ID of the document's custom type, and uid refers to the document's UID.

Copy
// Update the path for your API client file.
import { Client } from '../path-to-your-API-client-config'

// Syntax: getByUID(type, uid)
const document = await Client().getByUID('blog-post', 'hello-world')

Query by Type

For more specific queries, you can use Prismic's predicates. Predicates are search parameters. To get all documents of a certain type, you'd use a predicate to search for all documents where the type matches a given value.

Copy
import Prismic from "@prismicio/client";
// Update the path for your API client file.
import { Client } from '../path-to-your-API-client-config'

// Syntax: getByUID('document.type', type)
const document = await Client().query(Prismic.Predicates.at('document.type', 'product'))

Query all Documents

Used for building more advanced queries. query is either a predicate function or an empty string. An empty string returns all documents.

Copy
// Update the path for your API client file.
import { Client } from '../path-to-your-API-client-config'

// Syntax: client.query(query)
const document = await Client().query('')

Further Learning: Advanced Queries

These queries can accept an options object and a callback function as additional arguments, like this:

client.getByUID( custom-type, uid, options )

Furthermore, client.query() can perform extremely powerful and specific searches.

You can learn more about options, callbacks, and advanced queries in the Advanced Queries section of the React documentation.

In Pages

In pages, you can use Next's getStaticProps method to query the Prismic API. Here's an example of what a query might look like in a ~/pages/[uid].js file. We're rendering a title and the Slice Zone:

Copy
import React from 'react'

// Update the path for your API client file.
import { Client } from '../path-to-your-API-client-config'
import { RichText } from 'prismic-reactjs'

// Update the paths for your functions and component files.
import SliceZone from "../path-to-your-slicezone-component";

const Post = ({ post }) => {
  return (
    <>
     {RichText.asText(post.data.title)}
     <SliceZone sliceZone={post.data.body} />
    </>
  )
}

export async function getStaticProps({params}) {
  const post = (await Client().getByUID('page', params.uid)

  return {
    props: {
      post,
    },
  }
}

export async function getStaticPaths() {
  const docs = await Client().query(
    Prismic.Predicates.at('document.type', 'page'),
    { lang: '*' }
  );
  return {
    paths: docs.results.map((doc) => {
      return { params: { uid: doc.uid }};
    }),
    fallback: false,
  };
}

export default Post

In Components

In components, you can use Next's fetch method to query the Prismic API. Note, unlike asyncData, fetch does not return data, but instead updates properties that are already initialized. Here's an example in ~/components/header.js:

Copy
import React from 'react'
// Update the path for your API client file.
import { Client } from '../path-to-your-API-client-config'

// Update the paths for your functions and component files.
import SliceZone from "../path-to-your-slicezone-component";

const Home = ({ home }) => {
  return (
    <>
     {RichText.asText(home.data.title)}
     <SliceZone sliceZone={home.data.body} />
    </>
  )
}

export async function getStaticProps() {
  const home = await Client().getSingle('homepage')

  return {
    props: {
      home,
    }
  }
}

Query by Language

Prismic allows you to publish your content in different languages. By default, the API will return content in your master language.

You can make your website language dynamic by using the lang URL param to query your content by language. Refer to the dedicated Multilingual templating documentation for more details.


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.