SEO for Sanity and NextJS: A DIY Guide

SEO for Sanity and NextJS: A DIY Guide

March 17, 2024

tl;dr: you need to enjoy struggling with Google Search Console. But it's fun.


SEO is an adventure for many developers and content creators. It’s a blend of art and science, and while it can be enjoyable, it’s often best left to the experts. This article serves as a dual-purpose guide: part to-do list and part explanatory manual. As I enhance my blog, I’ll update this piece with new insights and features.

Default and Dynamic Metadata

Setting up metadata in NextJS is relatively straightforward. The Metadata API provided by NextJS is robust and user-friendly, allowing for both default and dynamic metadata configurations. Reminder: don't forget to set up canonical data.

The official documentation is quite straightforward.

export async function generateMetadata({ params }: Props) {
  const post = await getArticleBySlug(params.slug);

  return {
    title: post.title + " | Artificial unIntelligence",
    description: getExcerpt(toPlainText(post.body)),
    alternates: {
      canonical: `${params.slug}`,
    openGraph: {
      title: post.title + " | Artificial unIntelligence",
      description: getExcerpt(toPlainText(post.body)),
      type: "article",
      images: [
          url: urlFor(post.mainImage).url(),

Sitemap Essentials

I’ve previously discussed sitemaps in another article. The key to a successful sitemap lies in its implementation. Stay tuned for more tricks and tips on this topic.

Optimizing Website Performance

Concerns about website performance can take a backseat for now. My site runs lean, with minimal third-party code—just a touch of Google Tag Manager and Google Analytics. Thanks to server-side rendering (SSR), the loading speed and overall performance are exceptional. However, there’s always room for improvement, particularly in image rendering and introducing pagination on the homepage.

I run PageSpeed Insights when I push a new version and so far, so good. Not great, but not bad as well.

Ok-ish results on PageSpeed Insights

The Role of Tags and Categories

As Google’s algorithms become increasingly sophisticated, tags and categories are losing their once-critical importance. They’re still on my to-do list, though, as they contribute to a more organized site structure. The challenge lies in managing routes effectively, ensuring that articles with multiple tags or categories are accessible through intuitive paths. For instance, both /blog/food/article and /blog/article should lead users to the same content.

The Author Field

Currently, I’m the sole author of this blog, which makes the author field less of a priority. There was a time when being listed in Google News was beneficial for visibility, but that era has likely passed. Nonetheless, it adds a personal touch that I enjoy.

Non-default SEO content

Some articles might need me to manually set a title/description. It's quite easy in Sanity I just need to add another block and fetch the data if needed.

import { defineType, defineArrayMember } from "sanity";

 * This is the schema type for block content used in the post document type
 * Importing this type into the studio configuration's `schema` property
 * lets you reuse it in other document types with:
 *  {
 *    name: 'someName',
 *    title: 'Some title',
 *    type: 'blockContent'
 *  }

export default defineType({
  title: "Block SEO",
  name: "blockSeo",
  type: "object",
  fields: [
      title: "Title",
      name: "title",
      type: "string",
      validation: (Rule) =>
        Rule.max(60).warning(`A title shouldn't be more than 60 characters.`),
      title: "Description",
      name: "description",
      type: "text",
      validation: (Rule) =>
          `A description shouldn't be more than 120 characters.`

Final words

Stay tuned for updates as I continue to refine the SEO strategy for my blog, ensuring it remains both a practical resource and a testament to the evolving nature of web development and content creation.