The root layout was stamping the homepage title and production root onto every page. Routes now supply a page segment through one em-dash template, canonicals follow the request path, and non-production hosts disallow crawlers. Co-authored-by: Cursor <cursoragent@cursor.com>
75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { notFound } from "next/navigation";
|
|
import messages from "../../../../messages/en/index";
|
|
import { getPublicPublishedRuleById } from "../../../../lib/server/publishedRules";
|
|
import { parsePublishedDocumentForCommunityRuleDisplay } from "../../../../lib/create/publishedDocumentToDisplaySections";
|
|
import { routeMetadata } from "../../../../lib/siteMetadata";
|
|
import CommunityRule from "../../../components/type/CommunityRule";
|
|
import HeaderLockup from "../../../components/type/HeaderLockup";
|
|
|
|
interface PageProps {
|
|
params: Promise<{ id: string }>;
|
|
}
|
|
|
|
export async function generateMetadata({
|
|
params,
|
|
}: PageProps): Promise<Metadata> {
|
|
const { id } = await params;
|
|
const rule = await getPublicPublishedRuleById(id);
|
|
if (!rule) {
|
|
return {
|
|
title: messages.pages.ruleDetail.notFoundTitle,
|
|
description: "The requested CommunityRule could not be found.",
|
|
};
|
|
}
|
|
const description =
|
|
typeof rule.summary === "string" && rule.summary.trim().length > 0
|
|
? rule.summary
|
|
: undefined;
|
|
return routeMetadata(`/rules/${rule.id}`, {
|
|
title: rule.title,
|
|
description,
|
|
openGraph: {
|
|
title: rule.title,
|
|
description,
|
|
type: "article",
|
|
url: `/rules/${rule.id}`,
|
|
siteName: messages.metadata.siteName,
|
|
},
|
|
twitter: {
|
|
card: "summary_large_image",
|
|
title: rule.title,
|
|
description,
|
|
},
|
|
});
|
|
}
|
|
|
|
export default async function PublicRuleDetailPage({ params }: PageProps) {
|
|
const { id } = await params;
|
|
const rule = await getPublicPublishedRuleById(id);
|
|
if (!rule) {
|
|
notFound();
|
|
}
|
|
|
|
const sections = parsePublishedDocumentForCommunityRuleDisplay(rule.document);
|
|
const description =
|
|
typeof rule.summary === "string" && rule.summary.trim().length > 0
|
|
? rule.summary
|
|
: undefined;
|
|
|
|
return (
|
|
<div className="min-h-screen bg-[var(--color-teal-teal50,#c9fef9)]">
|
|
<div className="mx-auto flex max-w-[1200px] flex-col gap-[var(--measures-spacing-1200,48px)] px-5 py-[var(--spacing-scale-048,48px)] md:px-12 md:py-[var(--spacing-scale-064,64px)]">
|
|
<HeaderLockup
|
|
title={rule.title}
|
|
description={description}
|
|
justification="left"
|
|
size="L"
|
|
palette="inverse"
|
|
/>
|
|
<CommunityRule sections={sections} />
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|