Next.js SEO Guide: A Complete Checklist to Improve Your Site's Visibility
By: Bushra Islam - Updated: December 18, 2024
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:
- Experience working with Next.js
- Knowledge of JavaScript
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
- On-page SEO focuses on optimizing elements within your website, including content, meta tags, headers, and internal linking, to enhance search engine rankings and user experience.
- Off-page SEO Involves activities outside your website, such as building high-quality backlinks and improving your social media presence, to boost your site’s authority and trustworthiness.
- Technical SEO ensures that search engines can effectively crawl and index your site by optimizing factors such as site speed, mobile-friendliness, structured data, and site architecture.
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:
- Metadata
- Jason LD Schema
- Favicon
- Sitemap
- Robots.txt
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:
- title: The title that appears in search results and browser tabs
- description: A summary of the page content that appears in search results
- robots: Data for robots.txt file. It determines whether to index your web page or not.
- openGraph: Metadata for social media sharing on platforms like Facebook
- Twitter/X: Similar to OpenGraph, but specifically for Twitter/X
- alternates: Specifies alternative versions of the page, including canonical URLs
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.
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.