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

Reducing Operational Costs with AI Chatbots: A Smart Business Move featured image
December 29, 2025
Operational costs often rise because teams spend too much time on repetitive, low-value work. This article explains how AI chatbots reduce those costs by deflecting routine requests, shortening support interactions, automating back-and-forth workflows, and allowing businesses to scale without hiring linearly. It also shows how Anablock designs cost-effective AI chatbot solutions that deliver measurable automation savings while improving customer experience.
Cross-Industry Applications of AI Chatbots featured image
December 23, 2025
AI chatbots are no longer limited to basic FAQs. This article explores how the same conversational AI technology is being applied across healthcare, real estate, finance, hospitality, e-commerce, SaaS, and internal operations. You will see practical examples of how businesses use chatbots to automate repetitive tasks, improve responsiveness, and connect systems across industries, along with guidance on choosing the right starting use case.
10 CRM Admin Tasks You Should Automate with AI featured image
December 22, 2025
If being a CRM admin feels like nonstop cleanup, this article is for you. It breaks down ten time consuming CRM admin tasks that can be automated with AI, from deduplication and data enrichment to workflow monitoring and documentation. You will see how AI shifts CRM administration from manual maintenance to intelligent system design, and how Anablock helps make that transition practical and safe.

Unlock the Full Power of AI-Driven Transformation

Schedule Demo

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

Book Demo

Start a Support Agent

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

Call Now

Send us a Message

Summarize this page content with AI