Server side Pagination using contenful and Nextjs

Ebimene Agent
Software Engineer
December 15, 2023

Blog image

Prerequisites:

Before we dive into the implementation, ensure you have the following:

  1. A Next.js project set up.
  2. A Contentful account with a space and content model(this was shown in this article Building a Next.js Blog with Contentful Integration.

Step 1: Set Up Your Next.js Project:

npx create-next-app my-pagination-app
cd my-pagination-app

Step 2: Install Dependencies:

Install the necessary packages for Contentful and server-side pagination:

npm install contentful 

Step 3: Configure Contentful:

Set up a Contentful account and create a space. Define a content model for the items you want to paginate.Everything about how to create a space and getting your environment variables have been explained in this article attached:Building a Next.js Blog with Contentful Integration. Add many blogs to your space so you can implement pagination.

Step 4: Implement Server-Side Pagination:

Fetch Data Dynamically Create a utility function to fetch data from Contentful based on page and limit. Use the contentful package to interact with the Contentful API. You can create this function inside a lib folder or utils.We will be creating a file, contentful.js inside a utils folder. Add the following code to the contentful.js file

export const createContentClient = () => {
  return createClient({
    space: process.env.CONTENTFUL_SPACE_ID,
    accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
  })
}

const client = createContentClient()
export const getEntriesByType = async (
  type,
  page = 1,
  limit = 5,
) => {
  let skip = (page - 1) * limit
  const response = await client.getEntries({
    content_type: type,
    include: 2,
    limit,
    skip,
    order: ['-sys.createdAt'],
  })
  return response.items
}

The above code communicates with the contentful api endpoints to return items. We use the limit and skip values to return specific number of items and the number of items to ignore. You may need to read the contenful api docs to understand better how the skip and limit values work. We use the skip variable to return the number of items we want to ignore. We need 5 items per page(limit), so this value is defaulted to 5.We then use the page value (defaulted to 1) and limit values to control the skip value. We can get these values from the searchParams prop that is passed to a page by nextjs under the hood. The order parameter controls how you want to order your items from contentful. Hence " order: ['-sys.createdAt'] " returns the items(in our case, blogs) in the order of the date they were created.

We need three more functions that will be getting the total number of items, the blogs, and the one to get the contents of each blog.

export const getEntriesTotalNumber = async (type) => {
  const response = await client.getEntries({
    content_type: type,
  })

  return response.total
}
export const getEntryBySlug = async (slug, type) => {
  const queryOptions = {
    content_type: type,
    include: 2,
    'fields.slug[match]': slug,
  }
  const queryResult = await client.getEntries(queryOptions)
  return queryResult.items[0]
}

export const getBlogPosts = async (page, limit) => {
  const blogs = await getEntriesByType('blogPost', page, limit)
  const blogPosts = blogs.map((blog) => blog.fields)
  return blogPosts
}

We can now call these functions in the pages that we need them. Go to where you want to render your list of blogs(it could be blogs.js inside your app's folder or the home page). Add the following code to the page where you want to render the list.

import Link from "next/link";
import { getBlogPosts, getEntriesTotalNumber } from "./utils/contentful";
import styles from "./page.module.css";

export default async function Home({ searchParams }) {
  const page =
    typeof searchParams.page === "string" ? Number(searchParams.page) : 1;
  const limit =
    typeof searchParams.limit === "string" ? Number(searchParams.limit) : 5;

  const blogs = await getBlogPosts(page, limit);
  const totalBlogs = await getEntriesTotalNumber("blogPost");
  const hasPreviousPage = page > 1;
  const hasNextPage = totalBlogs > page * limit;

  return (
    <div className={styles.main}>
      <h1>Latest Blog Posts</h1>
      <ul>
        {blogs.map((blog) => (
          <div key={blog.slug} className={styles.blog}>
            <Link href={`${blog.slug}`}> {blog.title}</Link>
          </div>
        ))}
      </ul>
      <div className={styles.pageNavLinks}>
        <Link
          href={`/?page=${hasPreviousPage ? page - 1 : 1}`}
          style={!hasPreviousPage ? { pointerEvents: "none" } : {}}
        >
          Previous
        </Link>
        <Link
          href={`/?page=${hasNextPage ? page + 1 : page}`}
          style={!hasNextPage ? { pointerEvents: "none" } : {}}
        >
          Next
        </Link>
      </div>
    </div>
  );
}

You can customize the UI of your project to meet your needs. I added a very short css code to give the blogs list page a good design. Add this code to the page.module.css file that follows a default bare nextjs app.

Conclusion

By following these steps, you've successfully implemented server-side pagination in a Next.js application using Contentful. This approach ensures efficient data retrieval and provides a seamless experience for users navigating through paginated content. Feel free to customize the code further based on your specific requirements, and leverage the power of Contentful and Next.js to create high-performance web applications with dynamic pagination.

Share this article:
View all articles

Related Articles

Choosing the Right Data Sources for Training AI Chatbots featured image
December 12, 2025
If your AI chatbot sounds generic, gives wrong answers, or feels unreliable, the problem is probably not the model. It is the data behind it. In this article, you will see why choosing the right data sources matters more than any tool or framework. We walk through what data your chatbot should actually learn from, which sources help it sound accurate and confident, which ones quietly break performance, and how to use your existing knowledge without creating constant maintenance work. If you want a chatbot that truly reflects how your business works, this is where you need to start.
Lead Qualification Made Easy with AI Voice Assistants featured image
December 11, 2025
If your sales team is spending hours chasing leads that never convert, this is for you. Most businesses do not have a lead problem, they have a qualification problem. In this article, you will see how AI voice assistants handle the first conversation, ask the right questions, and surface only the leads worth your team’s time. You will learn how voice AI actually works, where it fits into real sales workflows, and why companies using it respond faster, close more deals, and stop wasting effort on unqualified prospects. If you want your leads filtered before they ever reach sales, keep reading.
The Automation Impact on Response Time and Conversions Is Bigger Than Most Businesses Realize featured image
December 9, 2025
This blog explains how response time has become one of the strongest predictors of conversions and why most businesses lose revenue not from poor marketing, but from slow follow up. It highlights how automation eliminates the delays that humans cannot avoid, ensuring immediate engagement across chat, voice, and form submissions. The post shows how automated systems capture intent at its peak, create consistent customer experiences, and significantly increase conversion rates by closing the gap between inquiry and response. Automation does not just improve speed. It transforms how the entire pipeline operates.

Unlock the Full Power of AI-Driven Transformation

Schedule a Demo

See how Anablock can automate and scale your business with AI.

Book Now

Start a Voice Call

Talk directly with our AI experts and get real-time guidance.

Call Now

Send us a Message

Summarize this page content with AI