How to get previous and next items of same type with GROQ?
You can retrieve previous and next items in GROQ by using comparison operators with ordering. Here's how to structure your query:
{
"post": *[_type == "news" && slug.current == $slug][0],
"prev": *[_type == "news" && _createdAt < *[_type == "news" && slug.current == $slug][0]._createdAt] | order(_createdAt desc)[0],
"next": *[_type == "news" && _createdAt > *[_type == "news" && slug.current == $slug][0]._createdAt] | order(_createdAt asc)[0]
}However, this approach queries the current post multiple times, which isn't efficient. A better pattern is to use a projection to avoid redundant queries:
*[_type == "news" && slug.current == $slug][0] {
...,
"prev": *[_type == "news" && _createdAt < ^._createdAt] | order(_createdAt desc)[0],
"next": *[_type == "news" && _createdAt > ^._createdAt] | order(_createdAt asc)[0]
}The ^ operator references the parent scope (the current post), so you can compare against its _createdAt field without re-querying.
Key points:
- Use
<to get items before the current one, thenorder(_createdAt desc)[0]to get the most recent previous item - Use
>to get items after the current one, thenorder(_createdAt asc)[0]to get the next item - Replace
_createdAtwith whatever field you want to use for ordering (likepublishedAt,orderRank, etc.) - The
^operator helps you reference the parent document's fields within projections
If you're ordering by a custom field like publishedAt or want to handle published vs draft documents, adjust the filter accordingly:
*[_type == "news" && slug.current == $slug && !(_id in path("drafts.**"))][0] {
...,
"prev": *[_type == "news" && !(_id in path("drafts.**")) && publishedAt < ^.publishedAt] | order(publishedAt desc)[0],
"next": *[_type == "news" && !(_id in path("drafts.**")) && publishedAt > ^.publishedAt] | order(publishedAt asc)[0]
}This pattern works well for pagination-style navigation through content of the same type. Just make sure the field you're ordering by is indexed properly for better query performance.
Show original thread14 replies
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.