GEO for SvelteKit: Complete Implementation Guide
intermediateSvelteKit implements GEO via the svelte:head element in +layout.svelte for site-wide meta tags, and per-page +page.svelte for article-specific data. Use prerender=true in +page.ts for static generation. JSON-LD is injected directly in svelte:head as a raw script tag.
GEO for SvelteKit: Complete Implementation Guide
SvelteKit implements GEO via the svelte:head element in +layout.svelte for site-wide meta tags, and per-page +page.svelte for article-specific data. Use prerender=true in +page.ts for static generation. JSON-LD is injected directly in svelte:head as a raw script tag.
SvelteKit uses SSR by default and can pre-render pages to static HTML — both options are AI-crawler compatible. The svelte:head element gives you direct control over every tag in the HTML head.
Page Implementation
<!-- src/routes/geo-guide/+page.svelte -->
<script lang="ts">
const publishedTime = '2026-04-18T00:00:00Z'
const url = 'https://yoursite.com/geo-guide'
const schema = JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Article',
headline: 'How to Implement GEO in SvelteKit',
author: { '@type': 'Organization', name: 'My Company' },
publisher: {
'@type': 'Organization',
name: 'My Site',
logo: { '@type': 'ImageObject', url: 'https://yoursite.com/logo.png' },
},
datePublished: publishedTime,
dateModified: publishedTime,
mainEntityOfPage: { '@type': 'WebPage', '@id': url },
})
</script>
<svelte:head>
<title>How to Implement GEO in SvelteKit | My Site</title>
<meta name="description" content="GEO in SvelteKit with svelte:head, Open Graph, and JSON-LD. Complete guide with examples.">
<meta name="author" content="My Company">
<link rel="canonical" href={url}>
<meta property="og:type" content="article">
<meta property="og:title" content="How to Implement GEO in SvelteKit">
<meta property="og:description" content="Complete technical GEO guide for SvelteKit">
<meta property="og:url" content={url}>
<meta property="og:site_name" content="My Site">
<meta property="og:image" content="https://yoursite.com/og/geo-guide.jpg">
<meta property="og:locale" content="en_US">
<meta property="article:published_time" content={publishedTime}>
<meta property="article:modified_time" content={publishedTime}>
<meta property="article:author" content="https://yoursite.com/author/my-company">
<meta property="article:section" content="Technical Guides">
<meta property="article:tag" content="GEO">
<meta name="robots" content="index, follow">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html `<script type="application/ld+json">${schema}</script>`}
</svelte:head>
<main>
<article>
<h1>How to Implement GEO in SvelteKit</h1>
<!-- Inverted pyramid: direct answer first -->
<p>
GEO in SvelteKit is implemented via svelte:head for all meta tags and
JSON-LD schema. SSR is the default, making pages accessible to AI crawlers.
</p>
</article>
</main>
Dynamic Pages with Load Functions
For CMS-driven content, load data in +page.ts and pass it to +page.svelte:
// src/routes/blog/[slug]/+page.ts
import type { PageLoad } from './$types'
export const load: PageLoad = async ({ params, fetch }) => {
const post = await fetch(`/api/posts/${params.slug}`).then(r => r.json())
return { post }
}
// Optional: prerender for static HTML output
export const prerender = false // true for fully static pages
<!-- src/routes/blog/[slug]/+page.svelte -->
<script lang="ts">
import type { PageData } from './$types'
export let data: PageData
const { post } = data
const schema = JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Article',
headline: post.title,
datePublished: post.publishedAt,
dateModified: post.updatedAt,
author: { '@type': 'Person', name: post.author.name },
publisher: { '@type': 'Organization', name: 'My Site' },
})
</script>
<svelte:head>
<title>{post.title} | My Site</title>
<meta name="description" content={post.excerpt}>
<link rel="canonical" href="https://yoursite.com/blog/{post.slug}">
<meta property="og:type" content="article">
<meta property="og:title" content={post.title}>
<meta property="article:published_time" content={post.publishedAt}>
<meta property="article:modified_time" content={post.updatedAt}>
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html `<script type="application/ld+json">${schema}</script>`}
</svelte:head>
<article>
<h1>{post.title}</h1>
{@html post.content}
</article>
Root Layout for Site-Wide Defaults
<!-- src/routes/+layout.svelte -->
<script lang="ts">
import { page } from '$app/stores'
</script>
<svelte:head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="index, follow">
</svelte:head>
<slot />
robots.txt
Create static/robots.txt (SvelteKit serves the static/ directory as root):
User-agent: GPTBot
Allow: /
User-agent: OAI-SearchBot
Allow: /
User-agent: ClaudeBot
Allow: /
User-agent: Claude-User
Allow: /
User-agent: Claude-SearchBot
Allow: /
User-agent: PerplexityBot
Allow: /
User-agent: Google-Extended
Allow: /
User-agent: BingBot
Allow: /
Sitemap: https://yoursite.com/sitemap.xml
Sitemap: https://yoursite.com/llms.txt
llms.txt
Create static/llms.txt:
# My Site Name
> Description of what your site does and who it serves.
## Main Content
- [GEO Guide](https://yoursite.com/geo-guide): Complete GEO implementation guide
- [Technical Reference](https://yoursite.com/technical): Meta tags, schema, robots.txt
## About
- [About](https://yoursite.com/about): Team credentials
Dynamic Sitemap Route
Create a server route that generates the sitemap:
// src/routes/sitemap.xml/+server.ts
import type { RequestHandler } from './$types'
export const GET: RequestHandler = async () => {
const pages = await getAllPages()
const sitemap = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://yoursite.com/</loc>
<lastmod>${new Date().toISOString().split('T')[0]}</lastmod>
<priority>1.0</priority>
</url>
${pages.map(page => `
<url>
<loc>https://yoursite.com/${page.slug}</loc>
<lastmod>${page.updatedAt.split('T')[0]}</lastmod>
<priority>0.8</priority>
</url>`).join('')}
</urlset>`
return new Response(sitemap, {
headers: { 'Content-Type': 'application/xml' },
})
}
Static Prerendering
For fully static output (maximum AI crawler compatibility):
// src/routes/+layout.ts
export const prerender = true
export const trailingSlash = 'always'
Or per-page:
// src/routes/geo-guide/+page.ts
export const prerender = true
GEO Checklist for SvelteKit
- SSR active (default) or prerender=true for static output
- svelte:head: title, description, canonical, author, robots
- Open Graph: og:type=article, og:title, og:description, og:url, og:site_name, og:image
- Article dates: article:published_time, article:modified_time
- JSON-LD via {@html} injection in svelte:head
- static/robots.txt with all 8 AI crawlers
- static/llms.txt with site description and page listing
- Dynamic sitemap.xml route with lastmod dates
- Inverted pyramid content structure
- Core Web Vitals: LCP < 2.5s, INP < 200ms, CLS < 0.1