Next.js SEO Guide: A Complete Checklist to Improve Your Site's Visibility

By: Bushra Islam - Updated: December 18, 2024

Next.js SEO Guide: A Complete Checklist to Improve Your Site's Visibility

SEO helps your business grow by making it easier for potential customers to find your website online.

By optimizing your site for search engines, SEO connects you with users searching for related topics, attracting meaningful visitors.

This guide will show you how to optimize your website for SEO and improve your online visibility.

Let’s dive in!

Prerequisites

To follow this guide you must have the following:

What is SEO?

Search Engine Optimization (SEO) is a set of practices and techniques designed to improve a website's visibility in search engine results pages. When users search for specific keywords or phrases related to your content, good SEO practices help your website rank higher in these results, making it more likely for users to find and visit your site.

There are three types of SEO: On-Page SEO, Off-Page SEO, and Technical SEO

In this article, we are going to focus on Technical SEO.

With technical SEO, you prepare your website for Search engines to crawl and index.

Here is the checklist for Technical SEO:

Let’s go through one by one.

Metadata

Metadata determines how search engines understand and display your website. It provides search engines and potential visitors with essential information about your web pages. Implementing metadata in Next.js is straightforward.

Next.js offers two ways to generate metadata one for Static pages, and another for Dynamic pages.

Let’s go through one by one.

Static Metadata

Static metadata is defined directly in your page components and remains constant. This approach is perfect for pages where the content doesn't change frequently, such as your home page, about page, or contact page.

The metadata values are set during build time and remain the same until the next deployment.

Here’s an example of blog archive page metadata:

export const metadata: Metadata = {
  title: "Blog | GridPixels",
  description:
    "Learn, grow, and get inspired with our blog. Find tutorials, tips, and expert advice to elevate your skills in Figma, Next.js, and project building.",
  keywords: [
    "next.js",
    "react",
    "figma",
    "tailwind",
    "javascript",
    "sanity cms",
  ],
  robots: {
    index: true,
    follow: true,
    nocache: true,
    googleBot: {
      index: true,
      follow: true,
      "max-video-preview": -1,
      "max-image-preview": "large",
      "max-snippet": -1,
    },
  },
  openGraph: {
    type: "website",
    title: "Blog | GridPixels",
    description:
      "Learn about Next.js, React.js and all the other frontend technologies.",
    images: [
      {
        url: `${url}/images/og-image.jpg`,
        width: 1200,
        height: 630,
        alt: "Blog | GridPixels",
      },
    ],
    url: `${url}/blog`,
  },
  twitter: {
    card: "summary_large_image",
    title: "Blog | GridPixels",
    description:
      "Learn about Next.js, React.js and all the other frontend technologies.",
    images: [
      {
        url: `${url}/images/og-image.jpg`,
        width: 1200,
        height: 630,
        alt: "Blog | GridPixels",
      },
    ],
  },

  alternates: {
    canonical: `${url}/blog`,
  },
};

Let's understand what each field means in the metadata:

Dynamic Metadata

You'll need to generate metadata dynamically for dynamic content like blog posts or product pages. This ensures that each page has unique, relevant metadata based on its content.

Here’s an example of blog post metadata:


You must use the generateMetadata function to return the metadata object for dynamic metadata.

The data is the same as the static metadata, we are just setting the post-specific data.

This is how you can generate dynamic metadata for your dynamic pages.

JSON-LD

JSON-LD (JavaScript Object Notation for Linked Data) is a simple way to structure data on your website, helping search engines understand and display your content effectively. It improves SEO by enabling features like rich snippets and knowledge graphs.

You can use Schema Markup Generator to generate the JSON-LD for your website:

Once you fill out the forms you will get an object like this:

const jsonLd = {
  "@context": "<https://schema.org>",
  "@type": "BlogPosting",
  mainEntityOfPage: {
    "@type": "WebPage",
    "@id": "<https://gridpixels.com/blog-post-link>"
  },
  headline: "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley",
  description:
    "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley",
  image:
    "<https://gridpixels.com/blog-post-link/post-image.png>",
  dateCreated: "2024-01-11T11:35:00+07:00",
  datePublished: "2024-01-11T11:35:00+07:00",
  dateModified: "2024-01-11T11:35:00+07:00",
  author: {
    "@type": "Bushra",
    name: "Bushra Islam",
    url: "<https://www.x.com/bushracodes>"
  },
  publisher: {
    "@type": "Organization",
    name: "GridPixels",
    logo: {
      "@type": "ImageObject",
      url: "<https://gridpixels.com/logo.png>"
    }
  },
  inLanguage: "en-US",
  isFamilyFriendly: "true"
};

Now that you have the structure of the data, you can update it with real data.

Here’s an example of how to add the JSON-LD data into a blog post.

const SingleBlogPage = async ({ params }: { params: { slug: string } }) => {
  const post = await getPostBySlug(params.slug);

  const jsonLd = {
  ...
  };

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
      />
    </>

  );
};

To learn more about JSON-LD check-out these resources:

Next.js JSON-LD: How to Add Structured Data to

Add Structured Data to your Next.js site with JSON-LD for better SEO

Favicon

Favicon is the icon you see on the browser’s status bar and the search page when you search your website.

blog image

Adding a favicon is super easy in Next.js, replace the existing favicon with the one you generated.

You can generate a favicon from these sites:

Favicon.io - The Ultimate Favicon Generator (Free)

Sitemap.ts

Sitemap helps search engine crawlers understand which pages to crawl and index.

You can create a sitemap very easily.

On the root of your project create a file named sitemap.ts.

Now paste this code into that file:

const URL = process.env.SITE_URL;

export default async function sitemap() {
  const staticPages = [
    {
      path: "/",
      priority: 1,
    },
    {
      path: "/about",
      priority: 0.9,
    },
    {
      path: "/contact",
      priority: 0.9,
    }
  ];

  const routes = staticPages.map(({ path: route, priority }) => ({
    url: `${URL}${route}`,
    lastModified: new Date().toISOString(),
    changeFrequency: "daily",
    priority: priority,
  }));

  return [...routes];
}

As you can see an array of StaticPages is used to generate a sitemap for the static pages.

For dynamic pages like blog posts or products, you have to fetch the posts and add them to the sitemap array.

Here’s a quick example of generating a sitemap for Static and Dynamic pages:

const URL = process.env.SITE_URL || "https://default-url.com";
import { getPosts } from "@/sanity/sanity-utils";

export default async function sitemap() {
  const staticPages = [
    { path: "/", priority: 1 },
    { path: "/about", priority: 0.9 },
    { path: "/contact", priority: 0.9 },
  ];

  const posts = (await getPosts()) || [];

  const routes = staticPages.map(({ path: route, priority }) => ({
    url: `${URL}${route}`,
    lastModified: new Date().toISOString(),
    changeFrequency: "daily",
    priority,
  }));

  const postRoutes = posts.map((post) => ({
    url: `${URL}/blog/${post?.slug?.current}`,
    lastModified: post?.updatedAt || new Date().toISOString(),
    changeFrequency: "daily",
    priority: 0.7,
  }));

  // Combine and return all routes
  return [...routes, ...postRoutes];
}

Robots.txt

Robots.txt is a file that tells search engine crawlers which pages they can or cannot crawl from your website.

It's like giving instructions to search engines about what they should and shouldn't look at your site.

Creating a robots.txt file in Next.js is straightforward. Create a robots.ts file in your app directory with these basic configurations:

export default function robots() {
  return {
    rules: {
      userAgent: '*',
      allow: '/',
      disallow: ['/private/', '/private-route-2'],
    },
    sitemap: 'https://yoursite.com/sitemap.xml',
  }
}

As shown above, you can have an array of disallowed routes. It will disable search engines from crawling the disallowed pages.

If you don’t specify on the robots page you can also add disallow on the metadata object

Conclusion

Optimizing SEO in Next.js is simple yet powerful. Use metadata effectively to boost visibility. Add sitemaps and robots.txt for better indexing. Implement favicons to enhance branding. Dynamic SEO ensures scalability. Follow these steps to rank higher and deliver a seamless user experience.

Additional Resources

Bushra Islam

Bushra Islam

Frontend developer

View Profile