Troubleshooting creating a button to link to the most recent blog using Next.js and Sanity.io API.

23 replies
Last updated: Nov 23, 2021
Is there a way I can create a button that would take me to index 0 of my blog, for instance I would want this button to always link to the most recent blog
AI Update

Yes, you can definitely create a button that always links to your most recent blog post! Here's how to approach this:

Using GROQ to Get the Most Recent Post

You'll want to write a GROQ query that fetches blog posts, sorts them by date, and grabs the first one. Here's an example:

*[_type == "blog"] | order(publishedAt desc)[0]

This query:

  1. Gets all documents with _type == "blog"
  2. Uses the order() function to sort by publishedAt in descending order (most recent first)
  3. Uses [0] to grab just the first item (index 0)

Once you have the most recent post, you can use its slug field to create your link. Here's a more complete query that projects just what you need:

*[_type == "blog"] | order(publishedAt desc)[0]{
  "slug": slug.current,
  title
}

Then in your frontend code (using Next.js as an example):

import Link from 'next/link'
import { client } from '@/sanity/lib/client'

async function LatestBlogButton() {
  const latestPost = await client.fetch(
    `*[_type == "blog"] | order(publishedAt desc)[0]{ "slug": slug.current }`
  )
  
  return (
    <Link href={`/blog/${latestPost.slug}`}>
      View Latest Post
    </Link>
  )
}

Important Notes

  • Make sure your blog schema has a date field (like publishedAt or _createdAt) to sort by
  • The [0] array indexing syntax grabs the first element after sorting
  • If you want to sort by creation time instead, you can use _createdAt which is automatically added to all documents
  • This approach will always dynamically fetch the most recent post, so the button will automatically update when you publish new content

This is a common pattern in Sanity and works great for "Latest Post" links, featured content, and similar use cases!

okay so I'm trying to have this button live in my navbar so my nav component file has the getServerSideProps of
export const getServerSideProps = async pageContext => {
    const query = encodeURIComponent('*[_type == "post"][0]');
    const url = `<https://cd0q2c94.api.sanity.io/v1/data/query/production?query=${query}>`;
    const result = await fetch(url).then(res => res.json());

    if (!result.result || !result.result.length) {
        return {
            props: {
                post: [],
            }
        }
    } else {
        return {
            props: {
                post: result.slug,
            }
        }
    }
}
and its returning undefined
Hm, a few thoughts here. You're using
v1
of the API, which could be causing some issues for you. Second, are you using Next? If so, the method you're using for querying your content here isn't your best option. You'd probably have an easier go of it if you use the next-sanity package.
ooh the tutorial I learned from must be outdated
yes i am using next
So now that I have that installed is there an easy way to achieve this?
Got it! Yeah, I would recommend making the switch to that package. It's fairly straightforward. First install the package, then set up the following:
/lib/sanity.js

import {createClient} from 'next-sanity'

const config = {
  dataset: <your-dataset-name>,
  projectId:<your-project-id>,
  apiVersion: '2021-10-21',
  useCdn: process.env.NODE_ENV === 'production'
}

export const sanityClient = createClient(config)

export const PortableText = createPortableTextComponent({
  ...config,
  serializers: {},
})
This file does a few things: it configures a client that you can use for querying and sets up a Portable Text component for serializing rich text.

Then, in your
getServerSideProps
we can change it to the following:
import { sanityClient } from './lib/sanity.js'

//other code

export const getServerSideProps = async pageContext => {
    const query = '*[_type == "post"][0]';
    const result = sanityClient.fetch(query)

    if (!result.length) {
        return {
            props: {
                post: [],
            }
        }
    } else {
        return {
            props: {
                post: result.slug,
            }
        }
    }
}
hmm is lib a folder that already exists or do I have to create? because I'm getting this
Ah, you would have to add
createPortableTextComponent
to your import from next-sanity. I left that out. It should look like this:
import { createClient, createPortableTextComponent } from next-sanity
And yes,
lib
is a directory that you would need to make to store your
sanity.js
file.
Okay so the { post } that I'm passing into my component from the props is still returning undefined, should I be passing it in another way?
I'm thinking it has something to do with me error handler
if (!result.length) {
        return {
            props: {
                post: [],
            }
        }
    }
beacuse its looking for an array but should be just 1 slug
try removing the
.length
That didnt do it, here's my component code
const Navbar = ({ post }) => {
    console.log(post)
    return ( 
        <nav className={styles.nav}>
            <ul className={styles.navList}>
                    <Link href="/">
                        <li className={styles.navItem}>
                            <a>Home</a>
                        </li>
                    </Link>
                    <Link href="/about">
                        <li className={styles.navItem}>
                            <a>About</a>
                        </li>
                    </Link>
                    <Link href={post}>
                        <li className={styles.navItem}>
                            <a>Blog</a>
                        </li>
                    </Link>
            </ul>
        </nav>
     );
}
I don't think it's that component that's causing the issue. Can you share how you configured your client? Have you added your frontend to your CORS origins?
I haven't done anything with cors, I created the next project with npx create-next-app and am making the api calls to sanity
You'll need to add the domain that you're currently using for your frontend to your CORS origins on manage.sanity.io . That's likely one of the reasons your queries aren't returning results. Did you add the correct projectID and dataset name to your client configuration as well?
I haveny deployed my next app yet, this is just local host
You still need to add a CORS origin
okay I added http://localhost:3000 to my CORS origin
I'm gettingError: Failed prop type: The prop
href
expects a
string
or
object
in
<Link>
, but got
undefined
instead.null
when I remove that from the Link, and try console logging it , It still sends undefined

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?