Page title generator on browser tab rebuilded.

This commit is contained in:
2026-09-08 14:25:15 +02:00
parent e16a18e488
commit 781e348ded
8 changed files with 128 additions and 19 deletions
+19 -4
View File
@@ -22,6 +22,7 @@ export type PageMetadata = {
locale?: string
title: string
}
/** robots directives — set to noindex/follow for legal/thin/search pages. */
robots?: {
follow: boolean
index: boolean
@@ -43,6 +44,13 @@ type BuildMetadataArgs = {
meta?: null | SeoMeta
/** Page title or site name first. Defaults to 'page-first'. */
order?: TitleOrder
/**
* The document's own title (e.g. page.title = 'Sprzątanie biur'). Used as the
* page-title source when meta.title is empty — the browser tab and search
* result should show the page name, not go blank, when an editor didn't fill
* the SEO title. Priority: titleOverride > meta.title > pageTitle.
*/
pageTitle?: null | string
/**
* Localized segment the document lives under (an archive page's slugs).
* Feeds both canonical and hreflang, so /pl/artykuly/moj-post and
@@ -82,16 +90,21 @@ export function buildMetadata({
locale,
meta,
order,
pageTitle,
prefix,
query,
separator,
siteName,
slugs,
}: BuildMetadataArgs): PageMetadata {
// titleOverride wins outright: an editor who filled it in wants that exact
// string in the tab, not a composition.
// Title source priority: titleOverride (exact, wins outright) > meta.title
// (SEO title an editor set) > pageTitle (the document's own name). This means
// a page with no SEO title still shows its name (e.g. 'Sprzątanie biur')
// composed with the site name, instead of just the site name or a blank.
const override = meta?.titleOverride?.trim()
const title = override || composeTitle({ order, pageTitle: meta?.title, separator, siteName })
const resolvedPageTitle = meta?.title?.trim() || pageTitle?.trim() || undefined
const title =
override || composeTitle({ order, pageTitle: resolvedPageTitle, separator, siteName })
const description = meta?.description?.trim() || undefined
const origin = baseUrl?.replace(/\/$/, '') ?? ''
@@ -116,12 +129,14 @@ export function buildMetadata({
...(canonical && { canonical }),
...(Object.keys(languages).length > 0 && { languages }),
},
...(meta?.noindex ? { robots: { follow: true, index: false } } : {}),
openGraph: {
title,
...(description && { description }),
...(images && { images }),
locale,
},
// noindex → tell search engines to exclude the page but still follow links
// (authority flows through). For legal/thin/search-result pages.
...(meta?.noindex ? { robots: { follow: true, index: false } } : {}),
}
}
+3
View File
@@ -43,6 +43,8 @@ type PageMetadataContext = {
type DocShape = {
id: number | string
meta?: null | SeoMeta
/** The document's own title (page name), used as the fallback page title. */
title?: null | string
}
/** plugin-seo stores the OG image as an upload relationship. */
@@ -151,6 +153,7 @@ export function createPageMetadata(args: CreatePageMetadataArgs) {
...base,
imageUrl: resolveOgImage(doc),
meta: doc.meta,
pageTitle: doc.title,
prefix,
query,
slugs,