Files
homepage/src/lib/components/Seo.svelte
T
Alexander 7e33ea833e feat(seo): sitemap, OG/canonical/hreflang, JSON-LD i18n
Add sitemap.xml route enumerating recipes, apologetik args, prayers, and
faith hubs. Drop /static/ from robots.txt — was blocking JSON-LD recipe
images from Google. Add reusable Seo component (OG/Twitter/canonical) and
wire into homepage, faith hub, recipes hub, and apologetik index.

Faith and recipe layouts now emit canonical + hreflang automatically by
swapping known lang slugs; deeper paths whose inner segments aren't safely
translatable (recipe [name], prayer [prayer], apologetik [argId]) are
skipped at the layout and may opt-in per page.

Recipe JSON-LD HowToStep names and baking instructions now resolve via
the recipes i18n table (jsonld_step / jsonld_bake / jsonld_for_duration +
existing at_temp) instead of being hardcoded German — English /recipes/
pages were emitting "Schritt N" in their schema.
2026-05-02 21:32:06 +02:00

58 lines
1.7 KiB
Svelte

<script lang="ts">
type Alternate = { hreflang: string; href: string };
interface Props {
title: string;
description?: string;
canonical?: string;
ogImage?: string;
ogImageAlt?: string;
ogType?: 'website' | 'article';
siteName?: string;
lang?: 'de' | 'en' | 'la';
alternates?: Alternate[];
twitterCard?: 'summary' | 'summary_large_image';
}
const {
title,
description,
canonical,
ogImage,
ogImageAlt,
ogType = 'website',
siteName = 'Bocken',
lang,
alternates = [],
twitterCard = 'summary_large_image',
}: Props = $props();
const localeMap = { de: 'de_DE', en: 'en_US', la: 'la' } as const;
</script>
<svelte:head>
<title>{title}</title>
{#if description}<meta name="description" content={description} />{/if}
{#if canonical}<link rel="canonical" href={canonical} />{/if}
<meta property="og:title" content={title} />
{#if description}<meta property="og:description" content={description} />{/if}
<meta property="og:type" content={ogType} />
<meta property="og:site_name" content={siteName} />
{#if canonical}<meta property="og:url" content={canonical} />{/if}
{#if lang}<meta property="og:locale" content={localeMap[lang]} />{/if}
{#if ogImage}
<meta property="og:image" content={ogImage} />
{#if ogImageAlt}<meta property="og:image:alt" content={ogImageAlt} />{/if}
{/if}
<meta name="twitter:card" content={twitterCard} />
<meta name="twitter:title" content={title} />
{#if description}<meta name="twitter:description" content={description} />{/if}
{#if ogImage}<meta name="twitter:image" content={ogImage} />{/if}
{#each alternates as a (a.hreflang)}
<link rel="alternate" hreflang={a.hreflang} href={a.href} />
{/each}
</svelte:head>