diff --git a/app/(app)/lish/[did]/[publication]/[rkey]/page.tsx b/app/(app)/lish/[did]/[publication]/[rkey]/page.tsx index e941d6e3..bb72ee44 100644 --- a/app/(app)/lish/[did]/[publication]/[rkey]/page.tsx +++ b/app/(app)/lish/[did]/[publication]/[rkey]/page.tsx @@ -2,11 +2,15 @@ import { supabaseServerClient } from "supabase/serverClient"; import { Metadata } from "next"; import { DocumentPageRenderer } from "./DocumentPageRenderer"; import { tryRenderPublicationPage } from "../tryRenderPublicationPage"; -import { normalizeDocumentRecord } from "src/utils/normalizeRecords"; +import { + normalizeDocumentRecord, + normalizePublicationRecord, +} from "src/utils/normalizeRecords"; import { documentUriFilter, publicationNameOrUriFilter, } from "src/utils/uriHelpers"; +import { getDocumentURL } from "app/(app)/lish/createPub/getPublicationURL"; export async function generateMetadata(props: { params: Promise<{ publication: string; did: string; rkey: string }>; @@ -47,7 +51,28 @@ export async function generateMetadata(props: { const docRecord = normalizeDocumentRecord(document.data); if (!docRecord) return { title: "404" }; + let publication = document.documents_in_publications[0]?.publications; + // Canonical URL points at the publication's blog domain so the post on + // leaflet.pub (and its quote pages, which inherit this metadata) doesn't + // compete with the custom-domain version in search results. + let canonical: string | undefined; + let feedTypes: Record | undefined; + if (publication) { + let url = getDocumentURL(docRecord, document.uri, publication); + if (url.startsWith("http")) canonical = url; + let pubRecord = normalizePublicationRecord(publication.record); + if (pubRecord?.url) { + feedTypes = { + "application/rss+xml": `${pubRecord.url}/rss`, + "application/atom+xml": `${pubRecord.url}/atom`, + "application/json": `${pubRecord.url}/json`, + }; + } + } + return { + alternates: + canonical || feedTypes ? { canonical, types: feedTypes } : undefined, icons: { icon: { url: diff --git a/app/(app)/p/[didOrHandle]/[rkey]/page.tsx b/app/(app)/p/[didOrHandle]/[rkey]/page.tsx index 95b94628..09ee9e81 100644 --- a/app/(app)/p/[didOrHandle]/[rkey]/page.tsx +++ b/app/(app)/p/[didOrHandle]/[rkey]/page.tsx @@ -5,6 +5,7 @@ import { DocumentPageRenderer } from "app/(app)/lish/[did]/[publication]/[rkey]/ import { NotFoundLayout } from "components/PageLayouts/NotFoundLayout"; import { normalizeDocumentRecord } from "src/utils/normalizeRecords"; import { documentUriFilter } from "src/utils/uriHelpers"; +import { getDocumentURL } from "app/(app)/lish/createPub/getPublicationURL"; export async function generateMetadata(props: { params: Promise<{ didOrHandle: string; rkey: string }>; @@ -36,7 +37,14 @@ export async function generateMetadata(props: { const docRecord = normalizeDocumentRecord(document.data); if (!docRecord) return { title: "404" }; + // Canonical URL points at the document's blog domain (doc.site + path) so + // the post on leaflet.pub (and its quote pages, which inherit this + // metadata) doesn't compete with the custom-domain version in search. + let docUrl = getDocumentURL(docRecord, document.uri); + let canonical = docUrl.startsWith("http") ? docUrl : undefined; + return { + alternates: canonical ? { canonical } : undefined, icons: { other: [ {