
Setting Up Blog Pagination in Astro with Sanity CMS
Build a beautiful blog with Astro and Sanity! This guide covers essential setups, pagination, and navigation for your blogging journey.
Last updated on: Nov 2024 Monday
๐ Prerequisites
Before diving into pagination, set up your blog with Astro and Sanity CMS. For a detailed setup guide, check out this article to get your Astro-Sanity blog foundation ready.
๐ Building Your Blog with Astro and Sanity CMS
Once youโve completed the basic setup, weโll focus on improving the user experience by implementing pagination. Hereโs a breakdown of the steps:
๐ 1: Update Blog Index Page for Pagination
Some changes in listing blogs on Astro frontend section
Let's assume we have a blog/index.astro page as follows with some changes to whatever you used when setting up using above link.
1---
2import BlogCard from "@/components/blog/blog-card.astro";
3import SiteData from "@/constants/siteData.json";
4import { getBlogs } from "@/helpers/server-actions";
5import Main from "../../components/Main.astro";
6import Layout from "../../layouts/Layout.astro";
7
8const blogs = await getBlogs();
9---
10
11<Layout
12 seo={{
13 title: SiteData.pages.blog.title,
14 description: SiteData.pages.blog.description
15 }}
16 keywords={SiteData.pages.blog.keywords}
17>
18 <Main className="mx-auto max-w-4xl pt-20 sm:pt-48">
19 {
20 blogs.length > 0 ? (
21 <>
22 <h1 class="bg-gradient-to-r from-[#ffff80] to-[#ff80bf] to-[60%] bg-clip-text pb-2 text-center text-2xl font-bold text-transparent sm:text-left sm:text-4xl md:text-5xl">
23 Discover: Blog Articles and More
24 </h1>
25 <div class="flex flex-col gap-10">
26 {blogs.map((blog) => (
27 <BlogCard key={blog._id} blog={blog} />
28 ))}
29 </div>
30 </>
31 ) : (
32 <p class="text-center text-2xl">No blogs found</p>
33 )
34 }
35 </Main>
36</Layout>
locate your blog listing page, typically named blog/index.astro. To enable pagination, rename it to blog/[...page].astro.
Replace the content in your updated blog/[...page].astro file with the following code:
1---
2import Main from "@/components/Main.astro";
3import Pagination from "@/components/Pagination.astro";
4import BlogCard from "@/components/blog/blog-card.astro";
5import SiteData from "@/constants/siteData.json";
6import { getAllBlogs } from "@/helpers/server-actions";
7import Layout from "@/layouts/Layout.astro";
8import type { GetStaticPaths, InferGetStaticPropsType } from "astro";
9
10type Props = InferGetStaticPropsType<typeof getStaticPaths>;
11
12export const getStaticPaths = (async ({ paginate }) => {
13 const blogs = await getAllBlogs();
14
15 return paginate(blogs, {
16 pageSize: 3
17 });
18}) satisfies GetStaticPaths;
19
20const { page } = Astro.props;
21
22const firstUrl = page.currentPage > 1 ? `/blog` : undefined;
23const lastUrl =
24 page.currentPage < page.lastPage ? `/blog/${page.lastPage}` : undefined;
25const prevUrl =
26 page.currentPage > 2 ? `/blog/${page.currentPage - 1}` : "/blog";
27const nextUrl =
28 page.currentPage < page.lastPage
29 ? `/blog/${page.currentPage + 1}`
30 : undefined;
31---
32
33<Layout
34 seo={{
35 title: SiteData.pages.blog.title,
36 description: SiteData.pages.blog.description
37 }}
38 keywords={SiteData.pages.blog.keywords}
39>
40 <Main className="mx-auto max-w-4xl pt-20 sm:pt-48">
41 {
42 page.data.length > 0 ? (
43 <>
44 <h1 class="bg-gradient-to-r from-[#ffff80] to-[#ff80bf] to-[60%] bg-clip-text pb-2 text-center text-2xl font-bold text-transparent sm:text-left sm:text-4xl md:text-5xl">
45 Discover: Blog Articles and More
46 </h1>
47 <div class="flex flex-col gap-10">
48 {page.data.map((blog) => (
49 <BlogCard key={blog._id} blog={blog} />
50 ))}
51 </div>
52
53 <Pagination
54 currentPage={page.currentPage}
55 lastPage={page.lastPage}
56 prevUrl={prevUrl}
57 nextUrl={nextUrl}
58 firstUrl={firstUrl}
59 lastUrl={lastUrl}
60 />
61 </>
62 ) : (
63 <p class="text-center text-2xl">No blogs found</p>
64 )
65 }
66 </Main>
67</Layout>
๐ 2: Create a Pagination Component
Pagination lets users easily navigate through multiple blog pages, so letโs build a Pagination component.
- Go to your components folder and create a new file named Pagination.astro at src/components/Pagination.astro.
- Add this code to manage page links dynamically:
src/components/Pagination.astro
1---
2import Link from "./Link.astro";
3
4const { currentPage, lastPage, prevUrl, nextUrl, firstUrl, lastUrl } =
5 Astro.props;
6
7const getPageNumbers = (current: number, last: number) => {
8 const range = [];
9 for (
10 let i = Math.max(1, current - 2);
11 i <= Math.min(last, current + 2);
12 i++
13 ) {
14 range.push(i);
15 }
16 return range;
17};
18
19const pageNumbers = getPageNumbers(currentPage, lastPage);
20const urlParam = Astro.url.pathname;
21---
22
23<div class="mt-8 flex items-center justify-center space-x-3">
24 {
25 firstUrl && currentPage > 1 && (
26 <Link
27 text="First"
28 href={firstUrl}
29 style="secondary"
30 classes="text-sm hover:bg-blue-50"
31 />
32 )
33 }
34
35 {
36 urlParam !== "/blog" && (
37 <Link
38 text="Previous"
39 href={prevUrl}
40 style="secondary"
41 icon={{ name: "tabler:arrow-big-left-line", side: "left" }}
42 classes="flex gap-2 items-center text-sm hover:bg-blue-50"
43 />
44 )
45 }
46
47 {
48 pageNumbers.map((page) => (
49 <Link
50 text={`${page}`}
51 href={page === 1 ? "/blog" : `/blog/${page}`}
52 style={page === currentPage ? "primary" : "secondary"}
53 classes={`rounded-full w-10 h-10 flex items-center justify-center ${
54 page === currentPage
55 ? "bg-blue-500 text-white"
56 : "bg-gray-100 text-gray-700 hover:bg-blue-50"
57 }`}
58 />
59 ))
60 }
61
62 {
63 nextUrl && (
64 <Link
65 text="Next"
66 href={nextUrl}
67 style="secondary"
68 icon={{ name: "tabler:arrow-big-right-line", side: "right" }}
69 classes="flex gap-2 items-center text-sm hover:bg-blue-50"
70 />
71 )
72 }
73
74 {
75 lastUrl && currentPage < lastPage && (
76 <Link
77 text="Last"
78 href={lastUrl}
79 style="secondary"
80 classes="text-sm hover:bg-blue-50"
81 />
82 )
83 }
84</div>
This component will allow visitors to navigate through your blog posts with ease.
๐ 3: Set Up a Link Component for Navigation
To streamline navigation, create a Link component, which will manage individual page links efficiently.
- Within src/components, add Link.astro.
Populate it with this code:
src/components/Link.astro
1---
2import { Icon } from "astro-icon";
3
4interface Props {
5 text: string;
6 href: string;
7 style: "primary" | "secondary";
8 icon?: {
9 name: string;
10 side: "left" | "right";
11 };
12 isFilled?: boolean;
13 borderVisible?: boolean;
14 classes?: string;
15}
16
17const {
18 text,
19 href,
20 style,
21 icon,
22 isFilled = true,
23 borderVisible = false,
24 classes,
25 ...rest
26} = Astro.props as Props;
27---
28
29<a
30 href={href}
31 class={`${
32 style === "primary" ? "bg-blue-500 text-white" : "bg-gray-200 text-gray-600"
33 } ${isFilled ? "rounded-full px-3 py-2" : "px-3 py-1"} ${
34 borderVisible ? "border border-gray-300" : ""
35 } ${classes} hover:shadow-md transition-all duration-150 ease-in-out`}
36 {...rest}
37>
38 {icon && icon.side === "left" && <Icon name={icon.name} class="w-5" />}
39 {text}
40 {icon && icon.side === "right" && <Icon name={icon.name} class="w-5" />}
41</a>
This will give you a seamless way to navigate through your blog pages. Enjoy building and sharing your thoughts with the world!
Don't forget to share this blog to your coding partners. Cheers ๐ฅ