Astro: Adding Previous and Next Post Navigation Links to Blog

Most blogs include navigation links that allow readers to move between entries. These links also strengthen internal linking, which can help search engines discover and understand related content. In Astro, this can be implemented with a reusable component and a small addition to the post layout.

Create the Navigation Component

Begin by creating a new component file named BlogPostNavPrevNext.astro.

AstroProject/
└── src/
    └── components/
        └── BlogPostNavPrevNext.astro

Include the following code in BlogPostNavPrevNext.astro.

This generates links for the previous and next posts by finding the index of the current post in the collection. After the collection is sorted by publication date, the component locates the current post within that ordered array. The neighboring array elements are then used to determine the previous and next posts, avoiding the need to store explicit links in frontmatter. If the current post is the most recent, the next post link is not shown. If it is the oldest, the previous post link is not shown.

If the collection filters unpublished entries, ensure the same filtering is applied here so navigation matches the posts visible elsewhere on the website.

In this example, the collection is named blog, and entries are shown from the /blog/ subdirectory. Adjust the code as needed.

This component is intended for use in individual post layouts where Astro.params.slug is populated. On paginated listing pages, that parameter is not present, so the component has no post to locate within the collection.

The calculated previous and next posts depend on how the collection is sorted and filtered before determining the current post’s index. Here, the collection is sorted in descending order by pubDate. If different sorting or filtering is used elsewhere, the order might change. With this descending sort, the previous post is the next-older entry, and the next post is the next-newer entry.

---
import { getCollection } from 'astro:content';

const posts = (await getCollection('blog'))
  .sort((a, b) => (b.data.pubDate?.valueOf() ?? 0) - (a.data.pubDate?.valueOf() ?? 0));

const currentPostIndex = posts.findIndex(post => post.id === Astro.params.slug);

const previousPost =
  ((currentPostIndex >= 0) && (currentPostIndex < posts.length - 1))
    ? posts[currentPostIndex + 1]
    : undefined;

const nextPost =
  currentPostIndex > 0
    ? posts[currentPostIndex - 1]
    : undefined;
---

{
  (previousPost || nextPost) && (
    <nav>
      {previousPost && (
        <p>
          Previous Post:
          <a href={`/blog/${previousPost.id}/`}>
            {previousPost.data.title}
          </a>
        </p>
      )}

      {nextPost && (
        <p>
          Next Post:
          <a href={`/blog/${nextPost.id}/`}>
            {nextPost.data.title}
          </a>
        </p>
      )}
    </nav>
  )
}

Add the Component to a Layout

To use the component, import BlogPostNavPrevNext into the layout file that displays blog entries. In this example, <BlogPostNavPrevNext /> is placed after the main content to show the previous and next post links before the page footer.

---
import BlogPostNavPrevNext from '../components/BlogPostNavPrevNext.astro';

const { title } = Astro.props;
---

<!doctype html>
<html lang="en">
  <head>
  </head>
  <body>
    <main>
      <article>
        <h1>{title}</h1>
      </article>
    </main>
    <BlogPostNavPrevNext />
  </body>
</html>

Summary

By locating the current entry within a sorted content collection, this component automatically generates links to adjacent posts without requiring additional frontmatter or manual maintenance. Placing the component in the post layout keeps navigation consistent across the blog while improving internal linking for both readers and search engines.