Skip to content

Commit 8ff3928

Browse files
committed
feat: add a sitemap
1 parent 2c90bd4 commit 8ff3928

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

pages/sitemap.xml.tsx

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { isEmpty, kebabCase } from 'lodash'
2+
import { GetServerSideProps } from 'next'
3+
4+
import * as converterModule from '@lib/converters'
5+
import type { Converter } from '@lib/converters'
6+
7+
/**
8+
* Placeholder - getServerSideProps() does all of the magic.
9+
*/
10+
// eslint-disable-next-line import/no-default-export
11+
export default function Sitemap() {
12+
return null
13+
}
14+
15+
/**
16+
* Decide what domain we want to use for the sitemap.
17+
*/
18+
const baseUrl = isEmpty(process.env.NEXT_PUBLIC_ANALYTICS_DOMAIN)
19+
? 'https://localhost:3000'
20+
: `https://${process.env.NEXT_PUBLIC_ANALYTICS_DOMAIN}`
21+
22+
/**
23+
* Build a list of page paths, by combining the static ones we
24+
* know about, with a list of the dynamic converters.
25+
*/
26+
const staticPaths = ['', 'about', 'privacy', 'security', 'terms']
27+
const converters = Object.values(converterModule)
28+
const converterPaths = converters
29+
.filter((cnv: Converter) => !cnv.isHidden)
30+
.map((cnv: Converter) => kebabCase(cnv.id))
31+
.map((id) => id.replace('java-script', 'javascript')) // Hyphenated looks non-standard.
32+
.map((id) => id.replace(/-(\d)/g, '$1')) // Replace eg. /md-5-encoder with /md5-encoder.
33+
const allPaths = [...staticPaths, ...converterPaths].sort()
34+
35+
/**
36+
* Generates an XML sitemap.
37+
*
38+
* @param context - The request context.
39+
*/
40+
export const getServerSideProps: GetServerSideProps = async ({ res }) => {
41+
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
42+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
43+
${allPaths
44+
.map((path) => {
45+
return `<url>
46+
<loc>${baseUrl}/${path}</loc>
47+
<lastmod>${new Date().toISOString()}</lastmod>
48+
<changefreq>daily</changefreq>
49+
<priority>1.0</priority>
50+
</url>
51+
`
52+
})
53+
.join('')}
54+
</urlset>
55+
`
56+
57+
res.setHeader('Content-Type', 'text/xml')
58+
res.write(sitemap)
59+
res.end()
60+
61+
return { props: {} }
62+
}

0 commit comments

Comments
 (0)