How to get the previous and next article based on publish date in a Groq query

10 replies
Last updated: Jul 31, 2022
me again 😂
is there a way to get prev/next of a type in a Groq query?

say i have
*[_type == 'article'] | order(publishDate desc)
... can i get the prev/next by extending this query?
AI Update

Yep, you can definitely get previous/next articles by extending your query! Here's the approach:

For a given article with a publishDate, you can fetch the next and previous articles using two separate queries with comparison operators:

const thisDate = post.publishDate

// Get next article (published after current)
const nextPage = await client.fetch(
  `*[_type == "article" && publishDate > "${thisDate}"] | order(publishDate) [0] {
    title, 
    publishDate, 
    slug
  }`
)

// Get previous article (published before current)
const prevPage = await client.fetch(
  `*[_type == 'article' && publishDate < "${thisDate}"] | order(publishDate desc) [0] {
    title, 
    publishDate, 
    slug
  }`
)

The key points here:

  • Use > to find articles published after the current date, then order(publishDate) ascending and grab [0] for the closest next one
  • Use < to find articles published before the current date, then order(publishDate desc) descending and grab [0] for the closest previous one

A note on edge cases: If multiple articles could have the exact same publishDate (same date AND time), you'll want to add _id to your ordering logic to ensure consistent results, similar to what's described in the GROQ pagination docs. But if you're the only editor and timestamps are always unique, you're probably fine with the simpler approach above.

You could also consider using GROQ parameters instead of string interpolation for cleaner, safer queries:

const nextPage = await client.fetch(
  `*[_type == "article" && publishDate > $date] | order(publishDate) [0]`,
  { date: thisDate }
)

This keeps your query more readable and avoids potential injection issues!

You may be interested in this documentation page: Paginating with GROQ
been reading and re-reading this to parse through how to execute this.
its talking about creating pagination through a huge number of documents (ie:
*[_type == 'article']

i'm looking to do this on a single article... get the article before and after it (based on my
publishDate
field).
trying to understand how to use something like
const currentArticle = article.publishDate
and then find article directly before/after this date.
maybe something like?
*[_type == "article" && publishDate > $currentArticle] | order(publishDate) [0]

so i've tested this in Vision in my studio and it works when i give it the
$currentArticle
as a string.
so i think i'm needing to understand the best way to pass a variable into my query
got them working by doing the following:

const thisDate = post.publishDate
const nextPage = await client.fetch(`*[_type == "article" && publishDate > "${thisDate}"] | order(publishDate) [0] {title, publishDate, slug}`)
const prevPage = await client.fetch(`*[_type == 'article' && publishDate < "${thisDate}"] | order(publishDate desc) [0] {title, publishDate, slug}`)
wondering if there is a more efficient way ... or perhaps pulling this into a function.

not sure if its necessary, but this seems verbose
Ah, if you just want the previous and next, yes, that’s how I would do it.
Note that if multiple articles could be published on the exact same
publishDate
, you will have to do a little more work here.
yeah, i was thinking the same... and would follow the directions from the link you gave above to incorporate the
lastId
part.
likely will add that shortly, but wanted to get the basics working first
actually, the more i think about this, i'm not sure i have to adjust anything.
unless there were 2 posts with the EXACT date AND time... which would basically be impossible since i'm the only editor and only use the studio and i set the date/time as a custom field.

but in a bigger, code based "make it foolproof" way i should probably update the query ...

lol
It is unlikely, true. 🙂

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.

Was this answer helpful?