This is a follow-up post to my previous post on Adding code syntax highlighting . If you want to follow up with this post you can find source code at this GitHub Revision.
Problem statement
As you may know that this blog was started based on the Learn Next.js Tutorial. That guide has already provided an excellent explanation of SEO. But the blog is missing SEO because it’s a Markdown-only blog. So based on that, I’ve prepared the following list of features I want at least for now:
- Dynamic Sitemap
- Dynamically add necessary meta tags for social media.
Solution
As you know the Next.js tutorial already has a guide on SEO. So, I’ll be following that to achieve the above goals.
Dynamic sitemap.xml
The Learn Next.js Tutorial has an example for a dynamic sitemap.xml. It uses Next.js SSR feature to dynamically return sitemap.xml.
So, I’ll be creating a new file under the pages sitemap.xml.tsx with the following content.
import { GetServerSideProps } from "next";
import { getAllCategoryIds, getSortedPostsData } from "../lib/posts";
const POSTS_ENDPOINT_URL = "https://www.example.com/posts";
const CATEGORIES_ENDPOINT_URL = "https://www.example.com/categories";
function generateSiteMap(
posts: { id: string }[],
categories: { id: string }[]
) {
return `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<!--We manually set the two URLs we know already-->
<url>
<loc>https://www.example.com</loc>
</url>
${posts
.map(({ id }) => {
return `
<url>
<loc>${`${POSTS_ENDPOINT_URL}/${id}`}</loc>
</url>
`;
})
.join("")}
${categories
.map(({ id }) => {
return `
<url>
<loc>${`${CATEGORIES_ENDPOINT_URL}/${id}`}</loc>
</url>
`;
})
.join("")}
</urlset>
`;
}
function SiteMap() {
// getServerSideProps will do the heavy lifting
}
export const getServerSideProps: GetServerSideProps = async ({ res }) => {
const posts = await getSortedPostsData();
const categoriesIds = await getAllCategoryIds();
const categories = categoriesIds.map((cat) => {
return { id: cat.params.id };
});
// We generate the XML sitemap with the posts data
const sitemap = generateSiteMap(posts, categories);
res.setHeader("Content-Type", "text/xml");
// we send the XML to the browser
res.write(sitemap);
res.end();
return {
props: {},
};
};
export default SiteMap;
Meta Tags
One of the reasons I wanted to fix SEO is links on social media. Adding a few tags related to social media sharing can give a better experience when sharing links on social media sites.
To add social media-related meta tags I made the following changes to pages/posts/[id.tsx] and lib/post.tsx
// pages/posts/[id.tsx]
// ...
export default function Post({
postData,
}: {
postData: {
title: string,
id: string,
description: string,
date: string,
contentHtml: string,
categories: string[],
},
}) {
return (
<Layout>
<Head>
<title>{postData.title}</title>
{/* metadata */}
<meta name="title" content={postData.title} />
<meta name="description" content={postData.excerpt} />
{/* og metadata */}
<meta property="og:type" content="website" />
<meta
property="og:url"
content={"https://www.example.com/posts/" + postData.id}
/>
<meta property="og:title" content={postData.title} />
<meta property="og:description" content={postData.excerpt} />
{/* twitter metadata */}
<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:title" content={postData.title} />
<meta
property="twitter:url"
content={"https://www.example.com/posts/" + postData.id}
/>
<meta property="twitter:description" content={postData.excerpt} />
</Head>
// ...
</Layout>
);
}
//...
// lib/post.tsx
// ...
export async function getPostData(id: string): Promise<{
date: string;
title: string;
id: string;
description: string;
contentHtml: string;
categories: string[];
}> {
//...
return {
id,
description: matterResult.data.excerpt ?? "Priyash Patil Blog",
contentHtml,
...(matterResult.data as { date: string; title: string }),
categories: matterResult.data.categories ?? ["Uncategorized"],
};
}
To get meta tags working we need to ensure we have the following front matter attributes in all Markdown files.
---
title: "Adding code syntax highlighting to my Next.js Markdown blog"
date: "2022-02-15"
description: "One of the very important feature of any tech blog is code syntax highlighting.
Browsers by default doesn't support code highlighting other than just very basic different font-family."
---
Missing robots.txt
For crawlers added robots.txt in the public directory with the following content.
# Allow all crawlers
User-agent: *
Allow: /
Source code
The final source code is on this GitHub Revision. Do note that this source repository is not my actual website. I’ll be maintaining a separate source code repository for this blog series.
Conclusion
I think the requirement of doing basic SEO is fulfilled. There’s a lot more to be done. SEO is not one time thing so in future I might have more posts on SEO coming up. So, stay tuned for that.
Keep the Conversation Going
I hope you found this post helpful! If you have any questions or feedback, feel free to reach out. You can also find me on X (Twitter) @priyashpatil for additional insights and updates on my latest content.