> ## Documentation Index
> Fetch the complete documentation index at: /docs/llms.txt
> Use this file to discover all available pages before exploring further.

# SvelteKit

> Use Fimo content, labels, native components, and optional Studio preview in SvelteKit.

SvelteKit owns routes, load functions, locale resolution, links, document
metadata, and per-page SEO. Fimo connects content, labels, source tracking, the
site-wide SEO defaults from Studio's SEO settings, and an optional Studio preview
bridge.

## Compatibility

The current adapter targets SvelteKit 2 with Svelte 5. The acceptance fixture
uses SvelteKit `2.70.2`, Svelte `5.56.8`, and Vite `8.2.0`. SvelteKit 1 and
Svelte 4 are outside the current tested boundary.

## Configure the runtime

```json theme={null}
{
  "runtime": { "framework": "sveltekit" }
}
```

Install `fimo-sveltekit` at the same version as `fimo`. It carries every SvelteKit surface: content, labels, components, the Vite plugin, and the hosting adapter.

> [tab] npm
>
> ```bash theme={null}
> npm install fimo fimo-sveltekit
> ```

> [tab] Bun
>
> ```bash theme={null}
> bun add fimo fimo-sveltekit
> ```

> [tab] pnpm
>
> ```bash theme={null}
> pnpm add fimo fimo-sveltekit
> ```

> [tab] Yarn
>
> ```bash theme={null}
> yarn add fimo fimo-sveltekit
> ```

Add Fimo's Vite plugin beside SvelteKit's plugin:

```ts theme={null}
import { sveltekit } from '@sveltejs/kit/vite';
import { fimo } from 'fimo-sveltekit/vite';
import { defineConfig } from 'vite';

export default defineConfig({ plugins: [fimo(), sveltekit()] });
```

This tags native Svelte elements during development for Studio source mapping.

For Fimo hosting, use the adapter:

```js theme={null}
// svelte.config.js
import { fimo } from 'fimo-sveltekit/config';

export default {
  kit: { adapter: fimo() },
};
```

It does not replace SvelteKit routing or alter production output.

## Content and labels

Use SvelteKit server `load` functions with the request event:

```ts theme={null}
import { createFimo } from 'fimo-sveltekit';
import { content } from '../../../schemas';

export async function load(event) {
  const fimo = createFimo({ content, event });
  const result = await fimo.articles.list({ limit: 12 });
  return { articles: fimo.articles.serialize(result.items) };
}
```

Pass `createFimo` the locale your application resolved. If you omit it, Fimo
sends `i18n.defaultLocale` from `.fimo/config.json`, and when that is unset the
API answers with your site default.

`getLabels` follows the same rule: add `locale` once your application resolves
one, and without it the API answers with your site default, which the
returned snapshot reports as its locale. Fetch labels in the root server layout
and pass the snapshot to `FimoProvider`. Fimo resolves the injected content API
URL internally; do not import a Fimo environment variable or hardcode a tenant
URL:

```ts theme={null}
import { getLabels } from 'fimo-sveltekit';

export async function load(event) {
  // If the app resolves a locale from its URL or session, pass it:
  // const locale = resolveLocale(event.url); // your app's resolver
  // return { labels: await getLabels({ event, locale }) };

  // Otherwise, omit it and use the Fimo project default.
  return { labels: await getLabels({ event }) };
}
```

```svelte theme={null}
<script lang="ts">
  import { FimoProvider } from 'fimo-sveltekit/components';
  import type { LayoutData } from './$types';
  import type { Snippet } from 'svelte';

  let { data, children }: { data: LayoutData; children: Snippet } = $props();
</script>

<FimoProvider labels={data.labels}>
  {@render children()}
</FimoProvider>
```

Render tracked values with native components from
`fimo-sveltekit/components`:

```svelte theme={null}
<script lang="ts">
  import { Image, RichText, Text } from 'fimo-sveltekit/components';
</script>

<Text value={article.title} as="h1" />
<RichText value={article.body} />
<Image value={article.cover} />
```

## SEO defaults

Resolve SEO in the existing server load and return `seoHead`. Preserve the
load's other data, including labels. A content page resolves after its read:
`resolveSeoForPath(event.url.pathname, config, { article })`, applies app
overrides, and returns its complete `seoHead` using `toSeoHead`.

```ts theme={null}
// src/routes/+layout.server.ts, or a content page's +page.server.ts
import { resolveSeoForPath, toSeoHead } from 'fimo/seo';
import config from '../../.fimo/config.json';

export function load({ url }) {
  const seo = resolveSeoForPath(url.pathname, config);
  return {
    seoHead: toSeoHead(seo, {
      canonicalUrl: seo?.url ? new URL(url.pathname, seo.url).href : undefined,
    }),
  };
}
```

Render the final merged route data from one head owner. A leaf load's
`seoHead` replaces the default head as a whole.

```svelte theme={null}
<!-- Inside the existing root layout, alongside its provider and children -->
<script lang="ts">
  import { page } from '$app/state';
  const head = $derived(page.data.seoHead ?? { meta: [], links: [] });
</script>

<svelte:head>
  <title>{head.title ?? 'My site'}</title>
  {#each head.meta as attributes}<meta {...attributes} />{/each}
  {#each head.links as attributes}<link {...attributes} />{/each}
</svelte:head>
```

New projects also return `siteSchemas: buildSiteSchemas(seo).map(serializeJsonLd)`
from the root load and render each entry in the same `<svelte:head>` with
``{@html `<script type="application/ld+json">${schema}</script>`}``. This is
the site's Organization and WebSite JSON-LD; it stays empty until the SEO
settings have a site name and URL.

Do not add a second page title beside root social tags. Use the same final
values for all tags and check client navigation, including returning to a page
without overrides. Existing apps can keep their current head component and
extend it in place.

The example canonical policy fits a root-hosted site; preserve existing
production domains, base paths and trailing slashes. Imported config needs
sync and rebuild/redeploy. Content freshness follows the app's load,
prerender and cache policy.

## Live preview

`FimoProvider` also owns the optional Studio preview runtime, including script
loading, SvelteKit navigation, and content refresh. Application code does not
need a Fimo server hook, a separate preview component, a preview environment
lookup, or a script tag.

## Boundaries

* SvelteKit owns routing, history, 404s, locale URLs, and per-page SEO; the root layout renders Fimo's site-wide SEO defaults.
* Fimo's Vite plugin owns development source tagging only.
* `FimoProvider` owns labels and the optional Studio preview bridge.
* Do not add React, React Query, or a Vite SPA fallback to SvelteKit.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.