The Future of Web Dev
The Future of Web Dev
Svelte Meta Tags for Svelte 5 SEO and JSON-LD
Set Svelte SEO metadata, social cards, canonical URLs, robots directives, and schema.org JSON-LD.

Svelte Meta Tags is a Svelte component library that manages page metadata and JSON-LD structured data.
MetaTags writes titles, descriptions, canonical URLs, robots directives, Open Graph data, and Twitter cards.
SvelteKit projects can keep site defaults in a root layout and merge page-level metadata with deepMerge.
Features
MetaTagscomponent for standard SEO and social metadata.JsonLdcomponent withschema-dtstypes for schema.org data.- SvelteKit helpers for layout defaults and page-level metadata.
- Recursive metadata overrides through
deepMerge. - Open Graph fields for basic objects, articles, books, profiles, videos, images, and audio.
- Twitter summary, large-image, app, and player card metadata.
- Language alternate links and mobile alternate URLs.
- Custom meta and link tags outside the predefined property set.
How To Use It
Install the package with npm:
npm install -D svelte-meta-tags
pnpm add -D svelte-meta-tags
yarn add -D svelte-meta-tagsOptional Svelte CLI Setup
Run this command if you want the add-on to wire up MetaTags:
npx sv add @sv-addon/svelte-meta-tagsBasic Usage
Import MetaTags into a page or layout. The component writes the generated metadata to <svelte:head>.
<script lang="ts">
import { MetaTags } from 'svelte-meta-tags';
</script>
<MetaTags
title="Pricing"
titleTemplate="%s | Acme"
description="Compare Acme plans and pricing."
canonical="https://acme.dev/pricing"
openGraph={{
type: 'website',
url: 'https://acme.dev/pricing',
title: 'Acme Pricing',
description: 'Compare Acme plans and pricing.',
images: [
{
url: 'https://acme.dev/images/pricing-og.jpg',
width: 1200,
height: 630,
alt: 'Acme pricing plans'
}
]
}}
twitter={{
cardType: 'summary_large_image',
site: '@acme',
title: 'Acme Pricing',
description: 'Compare Acme plans and pricing.',
image: 'https://acme.dev/images/pricing-og.jpg',
imageAlt: 'Acme pricing plans'
}}
/>Share Metadata Defaults Across SvelteKit Pages
defineBaseMetaTags freezes a metadata object and returns it as baseMetaTags. definePageMetaTags does the equivalent for pageMetaTags. deepMerge recursively merges nested objects, keeps the layout value when the page value is undefined, and replaces arrays in full.
+layout.ts
import { defineBaseMetaTags } from 'svelte-meta-tags';
import type { LayoutLoad } from './$types';
export const load: LayoutLoad = ({ url }) => {
const pageUrl = new URL(url.pathname, url.origin).href;
const baseTags = defineBaseMetaTags({
title: 'Acme',
titleTemplate: '%s | Acme',
description: 'Frontend infrastructure for modern web applications.',
canonical: pageUrl,
openGraph: {
type: 'website',
url: pageUrl,
siteName: 'Acme'
}
});
return { ...baseTags };
};+page.ts
import { definePageMetaTags } from 'svelte-meta-tags';
import type { PageLoad } from './$types';
export const load: PageLoad = () => {
const pageTags = definePageMetaTags({
title: 'Pricing',
description: 'Compare Acme plans and pricing.',
openGraph: {
title: 'Acme Pricing',
description: 'Compare Acme plans and pricing.'
}
});
return { ...pageTags };
};+layout.svelte
<script lang="ts">
import { page } from '$app/state';
import { MetaTags, deepMerge } from 'svelte-meta-tags';
let { data, children } = $props();
let metaTags = $derived(
deepMerge(data.baseMetaTags, page.data.pageMetaTags)
);
</script>
<MetaTags {...metaTags} />
{@render children()}Add JSON-LD Structured Data
JsonLd inserts "@context": "https://schema.org" automatically. Its output prop defaults to head. Set output="body" when the script should render at the component location.
<script lang="ts">
import { JsonLd } from 'svelte-meta-tags';
</script>
<JsonLd
schema={{
'@type': 'Article',
headline: 'Managing SEO Metadata in Svelte 5',
datePublished: '2026-09-10',
author: {
'@type': 'Organization',
name: 'Acme'
}
}}
/>Multiple Related Schemas
Use @graph when several related schema objects belong to one graph. A plain array is accepted.
<JsonLd
schema={{
'@graph': [
{
'@type': 'WebSite',
name: 'Acme',
url: 'https://acme.dev'
},
{
'@type': 'Organization',
name: 'Acme',
url: 'https://acme.dev'
}
]
}}
/>MetaTags Props
Three behaviors deserve attention before using the API reference. titleTemplate replaces every %s token with title and renders no <title> when title is absent. robots defaults to index,follow and renders a robots tag even when the prop is omitted. Set robots={false} to suppress that tag. A falsy robots value paired with additionalRobotsProps logs a console warning.
| Prop | Type | Purpose |
|---|---|---|
title | string | Page title |
titleTemplate | string | Title template with %s replacement |
robots | string | boolean | Robots directives |
additionalRobotsProps | AdditionalRobotsProps | Extra robots directives |
description | string | Meta description |
canonical | string | Canonical URL |
keywords | ReadonlyArray<string> | Meta keywords |
mobileAlternate | MobileAlternate | Alternate mobile URL and media query |
languageAlternates | ReadonlyArray<LanguageAlternate> | Alternate language URLs |
twitter | Twitter | Twitter card configuration |
facebook | Facebook | Facebook App ID metadata |
openGraph | OpenGraph | Open Graph configuration |
additionalMetaTags | ReadonlyArray<MetaTag> | Custom meta elements |
additionalLinkTags | ReadonlyArray<LinkTag> | Custom link elements |
Metadata Utilities
| Export | Purpose |
|---|---|
deepMerge(target, source) | Recursively merges layout and page metadata |
defineBaseMetaTags(obj) | Freezes MetaTagsProps and returns it under baseMetaTags |
definePageMetaTags(obj) | Freezes MetaTagsProps and returns it under pageMetaTags |
JsonLd Props
The schema prop uses schema-dts types and accepts one schema object, an array, or an @graph object.
| Prop | Type | Purpose |
|---|---|---|
schema | FlexibleSchema | FlexibleSchema[] | GraphWrappedThing | schema.org structured data |
output | "head" | "body" | Script location. Default: head |
Alternatives and Related Resources
- Manage SEO Metadata in Svelte Applications – Svelte SEO
- Complete Metadata Management for SvelteKit 5+ – SvelteKit SEO Component
FAQs
Q: Does svelte-meta-tags work outside SvelteKit?
A: Yes. MetaTags and JsonLd use Svelte head rendering and do not depend on SvelteKit internals. The +layout.ts, +page.ts, and deepMerge metadata pattern is specific to SvelteKit.
Q: Why did my default Open Graph images disappear after a page override?
A: deepMerge replaces a layout array when the page metadata defines an array for that property. Define the complete openGraph.images array in the page metadata when you override it.
Q: Do I need to add @context to JsonLd schema objects?
A: No. JsonLd automatically inserts "@context": "https://schema.org".


