Part of the "Conversations with AI" series where I share interesting and useful discussions with AI assistants. These conversations are lightly edited for clarity.
Now that I've posted to my blog over ten times, I ran into the scaling issue of only seeing the ten most recent posts on my homepage. When requesting the posts from my CMS, (WordPress), it responds with a maximum of ten posts by default. WordPress assumes that consumers will use pagination, meaning that page two of the blog will display the next ten posts. I hadn't programmed that feature yet, so I bumped the per_page
limit to eleven and added a comment reminding myself to replace the bandaid with a scalable solution.
export default async function Blog() {
// TODO: add pagination and remove per_page query
const posts = await fetch(`${WP_REST_URI}/posts?per_page=11`)
.then((res) => res.json()
Last week I implemented pagination like I've done for plenty of other projects, by storing the page number in the URL search query and using that value to request the appropriate posts from WordPress. I added those "next page" and "last page" buttons we all know and love to the bottom of the page and was done. However, this time, I didn't write any of the code. Features like this are so prolific in web development that AI can figure them out in seconds. And, if you code in an AI-enabled environment like Cursor, it can just do everything for you. Claude suggested all the code changes and all I had to do was apply and accept them.
So, I'm not even the engineer for my own site anymore! For features like this, my role is to delegate to the chatbots and review their code. This is a major productivity unlock that allows me to spend less time on backlog tasks and more on creative work. I used all the time it saved to build a component that displays AI chats for my blog. I'm going to start publishing "Conversations with AI" so that others can check out what I'm using it for. Here's the conversation between the developer of this commit and me.
// ... existing imports ...
// Add these new imports at the top
import { Pagination } from '@mui/material'
import { useSearchParams } from 'next/navigation'
export default async function Blog() {
const searchParams = useSearchParams()
const page = Number(searchParams.get('page')) || 1
const postsPerPage = 10
const posts = await fetch(
`${WP_REST_URI}/posts?per_page=${postsPerPage}&page=${page}`
).then((res) => res.json())
// Get total posts count from WordPress API headers
const totalPosts = parseInt(res.headers.get('X-WP-Total') || '0')
const totalPages = Math.ceil(totalPosts / postsPerPage)
return (
<Stack p={{ sm: 5, xs: 2 }} gap={5} mx="auto" maxWidth="50em">
<Typography component="h1">Blog</Typography>
{posts ? (
<Stack gap={{ sm: 5, xs: 2 }}>
<PostList posts={posts} />
<Stack spacing={2} alignItems="center">
<Pagination
count={totalPages}
page={page}
onChange={(_, value) => {
window.location.href = `?page=${value}`
}}
/>
<Typography textAlign="right">
{`displaying ${posts.length} post${posts.length > 1 ? 's' : ''} of ${totalPosts}`}
</Typography>
</Stack>
</Stack>
) : (
// ... existing error component ...
)}
</Stack>
)
}
Pagination
componentuseSearchParams
to get the current page from the URL// Remove useSearchParams import
// Add this type for the page props
type BlogProps = {
searchParams: { page?: string }
}
export default async function Blog({ searchParams }: BlogProps) {
const page = Number(searchParams.page) || 1
const postsPerPage = 10
const res = await fetch(
`${WP_REST_URI}/posts?per_page=${postsPerPage}&page=${page}`
)
const posts = await res.json()
const totalPosts = parseInt(res.headers.get('X-WP-Total') || '0')
const totalPages = Math.ceil(totalPosts / postsPerPage)
return (
<Stack p={{ sm: 5, xs: 2 }} gap={5} mx="auto" maxWidth="50em">
// ... existing code ...
{posts ? (
<Stack gap={{ sm: 5, xs: 2 }}>
<PostList posts={posts} />
<PaginationControls
totalPages={totalPages}
currentPage={page}
totalPosts={totalPosts}
displayedPosts={posts.length}
/>
</Stack>
) : (
// ... existing error component ...
)}
</Stack>
)
}
'use client'
import { Stack, Pagination, Typography } from '@mui/material'
import { useRouter } from 'next/navigation'
type PaginationControlsProps = {
totalPages: number
currentPage: number
totalPosts: number
displayedPosts: number
}
export function PaginationControls({
totalPages,
currentPage,
totalPosts,
displayedPosts
}: PaginationControlsProps) {
const router = useRouter()
return (
<Stack spacing={2} alignItems="center">
<Pagination
count={totalPages}
page={currentPage}
onChange={(_, value) => {
router.push(`?page=${value}`)
}}
/>
<Typography textAlign="right">
{`displaying ${displayedPosts} post${displayedPosts > 1 ? 's' : ''} of ${totalPosts}`}
</Typography>
</Stack>
)
}
Please visit my Wordpress site to leave a comment on this post.