feat(seo): noindex hook, recipe self-canonical, list-page metadata
CI / update (push) Successful in 37s
CI / update (push) Successful in 37s
Add X-Robots-Tag noindex,nofollow handler in hooks.server.ts for /api,
/login, /logout, /register, /settings, /tasks, /fitness, /cospend,
/expenses, and the recipe admin/edit/add/search/favorites/to-try paths.
Header-based so the rule lives in one place and covers JSON responses.
Recipe detail pages now emit a self-canonical pointing at the bare slug —
the layout helper deliberately skipped detail pages, leaving query-param
variants (?multiplier=2, ?utm=…) as duplicate URLs in Google's index.
Per-page Seo on list pages so each ranks for its category-level query:
- Apologetik contra/pro indices now use localized heading + lede instead
of hardcoded English descriptions
- Calendar month view title includes month + rite ("April 2026 ·
Liturgical Calendar (Vetus Ordo) — Bocken")
- Recipe /category, /tag, /icon, /season hub + detail pages get
descriptions via new *_meta_description and *_meta_prefix i18n keys
(added in both DE and EN locales)
This commit is contained in:
@@ -25,6 +25,32 @@ async function htmlLang({ event, resolve }: Parameters<Handle>[0]) {
|
||||
});
|
||||
}
|
||||
|
||||
/** Routes that must never appear in search-engine indexes. Search-results pages
|
||||
* are thin/duplicate content; admin/edit/auth-walled pages have no public value
|
||||
* and shouldn't burn crawl budget. Sets X-Robots-Tag rather than per-page meta
|
||||
* so the rule lives in one place and also covers JSON/API responses.
|
||||
*/
|
||||
const NOINDEX_PATTERNS: RegExp[] = [
|
||||
/^\/api(\/|$)/,
|
||||
/^\/(rezepte|recipes)\/(search|admin|administration|add|edit|favorites|to-try)(\/|$)/,
|
||||
/^\/login$/,
|
||||
/^\/logout$/,
|
||||
/^\/register(\/|$)/,
|
||||
/^\/settings(\/|$)/,
|
||||
/^\/tasks(\/|$)/,
|
||||
/^\/fitness(\/|$)/,
|
||||
/^\/cospend(\/|$)/,
|
||||
/^\/expenses(\/|$)/,
|
||||
];
|
||||
|
||||
async function noindex({ event, resolve }: Parameters<Handle>[0]) {
|
||||
const response = await resolve(event);
|
||||
if (NOINDEX_PATTERNS.some((p) => p.test(event.url.pathname))) {
|
||||
response.headers.set('X-Robots-Tag', 'noindex, nofollow');
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
async function timing({ event, resolve }: Parameters<Handle>[0]) {
|
||||
const marks: Record<string, number> = {};
|
||||
event.locals.timing = {
|
||||
@@ -162,6 +188,7 @@ export const handleError: HandleServerError = async ({ error, event, status, mes
|
||||
export const handle: Handle = sequence(
|
||||
timing,
|
||||
htmlLang,
|
||||
noindex,
|
||||
auth.handle,
|
||||
authorization
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user