Guest publishes remain share-by-link but stay out of the catalog and sitemap, and their pages send noindex until claimed. The published-rule view now uses heading and list markup matching Markdown export, and top banners sit below the header so Share is not covered. Co-authored-by: Cursor <cursoragent@cursor.com>
52 lines
1.3 KiB
TypeScript
52 lines
1.3 KiB
TypeScript
import type { MetadataRoute } from "next";
|
|
import { getAllBlogPosts } from "./content";
|
|
import { sitemapUrl } from "./siteMetadata";
|
|
import { USE_CASE_DETAIL_SLUGS } from "./useCaseSyntheticPost";
|
|
|
|
const STATIC_PUBLIC_PATHS = [
|
|
"/",
|
|
"/about",
|
|
"/learn",
|
|
"/templates",
|
|
"/blog",
|
|
"/use-cases",
|
|
"/how-it-works",
|
|
"/privacy",
|
|
"/terms",
|
|
"/cookies",
|
|
] as const;
|
|
|
|
/**
|
|
* Public marketing URLs for `/sitemap.xml`, plus listed published rules when
|
|
* the caller supplies them. Omits signed-in product routes (`/create`,
|
|
* `/login`, `/profile`), admin, and unlisted guest-claim `/rules/[id]`.
|
|
*/
|
|
export function buildPublicSitemap(
|
|
listedRules: ReadonlyArray<{ id: string; updatedAt: Date }> = [],
|
|
): MetadataRoute.Sitemap {
|
|
const entries: MetadataRoute.Sitemap = STATIC_PUBLIC_PATHS.map((path) => ({
|
|
url: sitemapUrl(path),
|
|
}));
|
|
|
|
for (const post of getAllBlogPosts()) {
|
|
entries.push({
|
|
url: sitemapUrl(`/blog/${post.slug}`),
|
|
lastModified: post.lastModified,
|
|
});
|
|
}
|
|
|
|
for (const slug of USE_CASE_DETAIL_SLUGS) {
|
|
entries.push({ url: sitemapUrl(`/use-cases/${slug}`) });
|
|
entries.push({ url: sitemapUrl(`/use-cases/${slug}/rule`) });
|
|
}
|
|
|
|
for (const rule of listedRules) {
|
|
entries.push({
|
|
url: sitemapUrl(`/rules/${encodeURIComponent(rule.id)}`),
|
|
lastModified: rule.updatedAt,
|
|
});
|
|
}
|
|
|
|
return entries;
|
|
}
|