Paginate your results

Prismic no longer recommends the gatsby-source-prismic-graphql plugin

With recent changes to Gatsby, Prismic no longer recommends the gatsby-source-prismic-graphql plugin that this documentation uses. Read more about the future of Prismic and Gatsby. We highly recommend using the gatsby-source-prismic instead. The documentation for this plugin can be found in the plugin's github README.

We will leave this documentation here for now, but will change it in the future when we determine the best approach for Prismic & Gatsby.

The results retrieved from the Prismic repository will automatically be paginated. Here you will find an explanation of how to modify the pagination parameters.

By default, pagination will be sorted by last publication date. If you would like to change that, specify a sortBy value in your page configuration in gatsby-config.js.

Before Reading

The Prismic GraphQL API returns a maximum of 20 documents per request. There is no way to increase this number, so this page explains how you can retrieve more than this initial 20 documents.

Limiting results to less than 20

If you want to limit the amount of results to less than 20 then you have two options you use — the first or last arguments. These are standard GraphQL arguments that you can use to get the first number of results in the array or the last number of results from the array.

first

In this example we'll get the first 2 blog posts from the results.

Copy
query {
  allPosts(first:2) {
    edges {
      node {
        _meta {
          uid
        }
      }
    }
  }
}

last

In this example we'll get the last 2 blog posts of that same array.

Copy
query {
  allPosts(last:2) {
    edges {
      node {
        _meta {
          uid
        }
      }
    }
  }
}

A cursor-based pagination

To access your document's data, you will have to go through two levels of information: edges and nodes.

Copy
query {
  allBlogs {
    edges {
      node {
        title
      }
    }
  }
}

These two levels allow us to provide more data to handle pagination.

Node

Each node represents a document published in the API for your request. At the node level, you will find a cursor that will provide a GraphQL ID for the document. This cursor is mainly helpful when you would like to query the documents that come before or after it.

Here is an example on how to get the cursor for your document:

Copy
query {
  allBlogs {
    edges {
      cursor
      node {
        title
      }
    }
  }
}

Edges

At the edges level, you can use the pageInfo field to get the first & last cursors of the list and to know if there are more pages of documents before or after the current one.

Here are the options available in the pageInfo field:

hasPreviousPage

boolean

Let's you know if there is a page of results before the current page

hasNextPage

boolean

Let's you know if there is a page of results after the current page

startCursor

string

Gives you the cursor of the item at the very beginning of all the results

endCursor

string

Gives you the cursor of the item at the very end of all the results

Here's an example that includes all these fields:

Copy
query {
  allBlog_posts {
    pageInfo {
      hasPreviousPage
      hasNextPage
      startCursor
      endCursor
    }
    edges {
      cursor
      node {
        title
      }
    }
  }
}

The after argument

Once you have a given cursor, you can use the after argument to retrieve the set of documents that come after it.

Copy
query {
  allBlog_posts(after:"YXJyYXljb25uZWN0aW9uOjE5") {
    edges {
      cursor
      node {
        title
      }
    }
  }
}

Mix this with the first argument to get just the next item:

Copy
{
  allBlog_posts(after: "YXJyYXljb25uZWN0aW9uOjQ=", first: 1) {
    edges {
      cursor
      node {
        title
      }
    }
  }
}

The before argument

Likewise, you can use the before argument to retrieve all the documents that come before the given cursor.

Copy
query {
  allBlog_posts(before:"YXJyYXljb25uZWN0aW9uOjQ=") {
    edges {
      cursor
      node {
        title
      }
    }
  }
}

Mix this with the last argument to get just the previous item:

Copy
{
  allBlog_posts(before: "YXJyYXljb25uZWN0aW9uOjQ=" last: 1) {
    edges {
      cursor
      node {
        title
      }
    }
  }
}

Full example with Next & Previous blog posts

Usually creating previous/next result pagination like this in Gatsby can be tricky because of static generation, but thanks to the gatsby-source-prismic-graphql plugin this has been made super easy.

Statically-Generated Pagination

For basic linking between the pages, metadata for the previous and next pages are provided to you automatically via pageContext in the paginationPreviousMeta and paginationNextMeta properties. These can be used in conjunction with your Link Resolver to generate links between pages without any additional GraphQL query.

Here is what your sample query should look like (for this example we're using our Gatsby blog sample):

Copy
// Query for the Blog Post content in Prismic
export const query = graphql`
query BlogPostQuery(
  $uid: String
  $paginationPreviousUid: String!
  $paginationPreviousLang: String!
  $paginationNextUid: String!
  $paginationNextLang: String!
) {
  prismic {
    allPosts(uid: $uid) {
      edges {
        node {
          _meta {
            id
            uid
            type
          }
          title
          date
          body {
            __typename
            ... on PRISMIC_PostBodyText {
              type
              label
              primary {
                text
              }
            }
            ... on PRISMIC_PostBodyQuote {
              type
              label
              primary {
                quote
              }
            }
            ... on PRISMIC_PostBodyImage_with_caption {
              type
              label
              primary {
                image
                caption
              }
            }
          }
        }
      }
    }
    prevArticle: post(uid: $paginationPreviousUid, lang: $paginationPreviousLang) {
      title
      _meta {
        uid
        lang
        type
      }
    }
    nextArticle: post(uid: $paginationNextUid, lang: $paginationNextLang) {
      title
      _meta {
        uid
        lang
        type
      }
    }
  }
}
`

Simple Example

We get this data from the query, set it as the pageContext and pass it to the previous/next buttons component.

Copy
export default (props) => {
  const {
    pageContext: { paginationPreviousMeta, paginationNextMeta }
  } = props

  // Define the Post content returned from Prismic
  const doc = props.data.prismic.allPosts.edges[0]
  if(!doc) return null

  return(
    <Layout>
      <PostBody blogPost={doc.node}/>
      <Pagination
        prevArticle={paginationPreviousMeta}
        nextArticle={paginationNextMeta}
      />
    </Layout>
  )
}

Then in the component template we pass these articles through the link resolver.

Copy
const Pagination = ({ nextArticle, prevArticle }) => (
  <div className="container">
    {prevArticle ? (
      <Link to={linkResolver(prevArticle)} aria-label="Previous Post">
        &larr;Previous
      </Link>
    ) : null}
    {prevArticle && nextArticle && ' -- '}
    {nextArticle ? (
      <Link to={linkResolver(nextArticle)} aria-label="Next Post">
        Next &rarr;
      </Link>
    ) : null}
  </div>
)

Advanced Example

For a more advanced example we get the blog post titles etc. from the data...

Copy
export default ({ data }) => {
  const {
    prismic: { prevArticle, nextArticle },
  } = data

  // Define the Post content returned from Prismic
  const doc = props.data.prismic.allPosts.edges[0]
  if(!doc) return null

  return(
    <Layout>
      <PostBody blogPost={doc.node}/>
      <EnhancedPagination
        prevArticle={prevArticle}
        nextArticle={nextArticle}
      />
    </Layout>
  )
}

Then pass that to the component:

Copy
const EnhancedPagination = ({ nextArticle, prevArticle }) => (
  <div className="container">
    {prevArticle ? (
      <Link to={linkResolver(prevArticle._meta)} aria-label="Previous Post">
        &larr; {RichText.asText(prevArticle.title || [], linkResolver)}
      </Link>
    ) : null}
    <div>{prevArticle && nextArticle && ' -- '}</div>
    {nextArticle ? (
      <Link to={linkResolver(nextArticle._meta)} aria-label="Next Post">
        {RichText.asText(nextArticle.title || [], linkResolver)} &rarr;
      </Link>
    ) : null}
  </div>
)

Need more?

Check out the README for the plugin on Github for more information about pagination.