Skip to content

Commit

Permalink
feat(templates): add sitemap support to website template (#9727)
Browse files Browse the repository at this point in the history
Adds sitemap support for website templates using `next-sitemap` and
dynamic sitemaps for pages and posts.
  • Loading branch information
paulpopus authored Dec 4, 2024
1 parent 1bd689b commit fce210b
Show file tree
Hide file tree
Showing 29 changed files with 411 additions and 44 deletions.
3 changes: 3 additions & 0 deletions templates/website/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ node_modules

# Payload default media upload directory
public/media/

public/robots.txt
public/sitemap*.xml
3 changes: 2 additions & 1 deletion templates/website/.npmrc
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
legacy-peer-deps=true
legacy-peer-deps=true
enable-pre-post-scripts=true
14 changes: 14 additions & 0 deletions templates/website/next-sitemap.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/** @type {import('next-sitemap').IConfig} */
const SITE_URL =
process.env.NEXT_PUBLIC_SERVER_URL ||
process.env.VERCEL_PROJECT_PRODUCTION_URL ||
'https://example.com'

module.exports = {
siteUrl: SITE_URL,
generateRobotsTxt: true,
exclude: ['/posts-sitemap.xml', '/pages-sitemap.xml', '/*', '/posts/*'],
robotsTxtOptions: {
additionalSitemaps: [`${SITE_URL}/pages-sitemap.xml`, `${SITE_URL}/posts-sitemap.xml`],
},
}
2 changes: 2 additions & 0 deletions templates/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"type": "module",
"scripts": {
"build": "cross-env NODE_OPTIONS=--no-deprecation next build",
"postbuild": "next-sitemap --config next-sitemap.config.cjs",
"dev": "cross-env NODE_OPTIONS=--no-deprecation next dev",
"dev:prod": "cross-env NODE_OPTIONS=--no-deprecation rm -rf .next && pnpm build && pnpm start",
"generate:importmap": "cross-env NODE_OPTIONS=--no-deprecation payload generate:importmap",
Expand Down Expand Up @@ -41,6 +42,7 @@
"jsonwebtoken": "9.0.2",
"lucide-react": "^0.378.0",
"next": "^15.0.3",
"next-sitemap": "^4.2.3",
"payload": "latest",
"payload-admin-bar": "^1.0.6",
"prism-react-renderer": "^2.3.1",
Expand Down
54 changes: 41 additions & 13 deletions templates/website/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { getServerSideSitemap } from 'next-sitemap'
import { getPayload } from 'payload'
import config from '@payload-config'
import { unstable_cache } from 'next/cache'

const getPagesSitemap = unstable_cache(
async () => {
const payload = await getPayload({ config })
const SITE_URL =
process.env.NEXT_PUBLIC_SERVER_URL ||
process.env.VERCEL_PROJECT_PRODUCTION_URL ||
'https://example.com'

const results = await payload.find({
collection: 'pages',
overrideAccess: false,
draft: false,
depth: 0,
limit: 1000,
pagination: false,
where: {
_status: {
equals: 'published',
},
},
select: {
slug: true,
updatedAt: true,
},
})

const dateFallback = new Date().toISOString()

const defaultSitemap = [
{
loc: `${SITE_URL}/search`,
lastmod: dateFallback,
},
{
loc: `${SITE_URL}/posts`,
lastmod: dateFallback,
},
]

const sitemap = results.docs
? results.docs
.filter((page) => Boolean(page?.slug))
.map((page) => {
return {
loc: page?.slug === 'home' ? `${SITE_URL}/` : `${SITE_URL}/${page?.slug}`,
lastmod: page.updatedAt || dateFallback,
}
})
: []

return [...defaultSitemap, ...sitemap]
},
['pages-sitemap'],
{
tags: ['pages-sitemap'],
},
)

export async function GET() {
const sitemap = await getPagesSitemap()

return getServerSideSitemap(sitemap)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { getServerSideSitemap } from 'next-sitemap'
import { getPayload } from 'payload'
import config from '@payload-config'
import { unstable_cache } from 'next/cache'

const getPostsSitemap = unstable_cache(
async () => {
const payload = await getPayload({ config })
const SITE_URL =
process.env.NEXT_PUBLIC_SERVER_URL ||
process.env.VERCEL_PROJECT_PRODUCTION_URL ||
'https://example.com'

const results = await payload.find({
collection: 'posts',
overrideAccess: false,
draft: false,
depth: 0,
limit: 1000,
pagination: false,
where: {
_status: {
equals: 'published',
},
},
select: {
slug: true,
updatedAt: true,
},
})

const dateFallback = new Date().toISOString()

const sitemap = results.docs
? results.docs
.filter((post) => Boolean(post?.slug))
.map((post) => ({
loc: `${SITE_URL}/posts/${post?.slug}`,
lastmod: post.updatedAt || dateFallback,
}))
: []

return sitemap
},
['posts-sitemap'],
{
tags: ['posts-sitemap'],
},
)

export async function GET() {
const sitemap = await getPostsSitemap()

return getServerSideSitemap(sitemap)
}
9 changes: 6 additions & 3 deletions templates/website/src/app/(frontend)/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ export default async function Page({ searchParams: searchParamsPromise }: Args)
<div className="pt-24 pb-24">
<PageClient />
<div className="container mb-16">
<div className="prose dark:prose-invert max-w-none">
<h1 className="sr-only">Search</h1>
<Search />
<div className="prose dark:prose-invert max-w-none text-center">
<h1 className="mb-8 lg:mb-16">Search</h1>

<div className="max-w-[50rem] mx-auto">
<Search />
</div>
</div>
</div>

Expand Down
14 changes: 12 additions & 2 deletions templates/website/src/collections/Pages/hooks/revalidatePage.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { CollectionAfterChangeHook } from 'payload'
import type { CollectionAfterChangeHook, CollectionAfterDeleteHook } from 'payload'

import { revalidatePath } from 'next/cache'
import { revalidatePath, revalidateTag } from 'next/cache'

import type { Page } from '../../../payload-types'

Expand All @@ -15,6 +15,7 @@ export const revalidatePage: CollectionAfterChangeHook<Page> = ({
payload.logger.info(`Revalidating page at path: ${path}`)

revalidatePath(path)
revalidateTag('pages-sitemap')
}

// If the page was previously published, we need to revalidate the old path
Expand All @@ -24,7 +25,16 @@ export const revalidatePage: CollectionAfterChangeHook<Page> = ({
payload.logger.info(`Revalidating old page at path: ${oldPath}`)

revalidatePath(oldPath)
revalidateTag('pages-sitemap')
}

return doc
}

export const revalidateDelete: CollectionAfterDeleteHook<Page> = ({ doc }) => {
const path = doc?.slug === 'home' ? '/' : `/${doc?.slug}`
revalidatePath(path)
revalidateTag('pages-sitemap')

return doc
}
Loading

0 comments on commit fce210b

Please sign in to comment.