This is the second step-by-step guide I’m publishing on how to enhance ShipFa.st (by Marc Lou), which has become my go-to boilerplate. ShipFa.st comes with an out-of-the-box support for blogging. It’s a great component that allows you to add content to your website (thus improving SEO) and provide move information to your customers.
What’s missing?
While the blogging feature of ShipFa.st is working great, it’s missing a key component – the various blog pages are missing from the Sitemap, making them less discoverable for search engines.
This step-by-step guide will help you solve that, and make sure your blog pages are all crawlable.
Adding a dynamic sitemap
We’ll start by implementing an endpoint/page that exposes a sitemap. Create a new file named route.ts
in the /app/server-sitemap.xml
folder, and add the following content::
// app/server-sitemap.xml/route.ts
import { ISitemapField, getServerSideSitemap } from 'next-sitemap'
import { categories, authors, articles } from "@/app/blog/_assets/content";
import config from "@/config";
export function GET(request: Request) {
const result:ISitemapField[] = []
categories.forEach(category => {
result.push({ loc: `https://${config.domainName}/blog/category/${category.slug}`, changefreq: 'weekly', priority: 0.7, lastmod: new Date().toISOString() })
});
authors.forEach(author => {
result.push({ loc: `https://${config.domainName}/blog/author/${author.slug}`, changefreq: 'weekly', priority: 0.7, lastmod: new Date().toISOString() })
});
articles.forEach(article => {
result.push({ loc: `https://${config.domainName}/blog/${article.slug}`, changefreq: 'weekly', priority: 0.7, lastmod: new Date().toISOString() })
});
return getServerSideSitemap(result)
}
At this point, you should be able to access the endpoint http://localhost:3000/server-sitemap.xml (use the correct port, based on your dev environment), and see something like this:
Exposing the new sitemap
Once we’re done with the sitemap content, it’s time to make sure it’s discoverable. We’ll include it in the regular sitemap index (hosted at /sitemap.xml
in your website), and we’ll also make sure that the endpoint itself doesn’t appear as a page in the “regular” sitemap. Open /next-sitemap.config.js
and make the following changes:
module.exports = {
...
exclude: [
...
(process.env.SITE_URL || "https://shipfa.st/") + 'server-sitemap.xml', // <==== Add this
],
robotsTxtOptions: {
additionalSitemaps: [
(process.env.SITE_URL || "https://shipfa.st/") + 'server-sitemap.xml', // <==== Add this
],
},
};
Conclusion
To paraphrase George Berkeley:
If a blog post is written in a website, and no one is around to crawl it, was it ever written?
Make sure to expose any dynamic page you generate in your site – a good starting point is whenever you have a dynamic route, you probably need to dynamically generate your sitemap.