Files
theater-ziefen-website/.agents/skills/sanity-best-practices/references/svelte.md
T
johannes.gasser 57af0b8386
Build and Deploy / build-and-deploy (push) Successful in 2m53s
add skills
2026-05-18 08:39:42 +02:00

3.9 KiB

title, description
title description
SvelteKit & Sanity Integration Rules Integration guide for SvelteKit with Sanity, including @sanity/svelte-loader, Visual Editing, and Preview Mode.

SvelteKit & Sanity Integration Rules

1. Setup & Configuration

Installation

npm install @sanity/svelte-loader @sanity/client @sanity/visual-editing

Client Configuration (src/lib/sanity.ts)

Define the client with stega enabled for the studio URL.

import { createClient } from '@sanity/client'
import { PUBLIC_SANITY_PROJECT_ID, PUBLIC_SANITY_DATASET, PUBLIC_SANITY_API_VERSION, PUBLIC_SANITY_STUDIO_URL } from '$env/static/public'

export const client = createClient({
  projectId: PUBLIC_SANITY_PROJECT_ID,
  dataset: PUBLIC_SANITY_DATASET,
  apiVersion: PUBLIC_SANITY_API_VERSION,
  useCdn: true,
  stega: {
    studioUrl: PUBLIC_SANITY_STUDIO_URL,
  },
})

Server Client (src/lib/server/sanity.ts)

Use the read token for fetching preview content.

import { SANITY_API_READ_TOKEN } from '$env/static/private'
import { client } from '$lib/sanity'

export const serverClient = client.withConfig({
  token: SANITY_API_READ_TOKEN,
  stega: true, // Optional: enable stega on server too if needed
})

2. Hooks & Request Handler (Critical)

You must configure createRequestHandler in src/hooks.server.ts to handle preview sessions and inject loadQuery into locals.

// src/hooks.server.ts
import { createRequestHandler, setServerClient } from '@sanity/svelte-loader'
import { serverClient } from '$lib/server/sanity'

setServerClient(serverClient)

export const handle = createRequestHandler()

Update app.d.ts types:

import type { LoaderLocals } from '@sanity/svelte-loader'

declare global {
  namespace App {
    interface Locals extends LoaderLocals {}
  }
}

3. Preview State Propagation

Pass the preview state from the server to the client via the root layout.

Server Layout (src/routes/+layout.server.ts):

import type { LayoutServerLoad } from './$types'

export const load: LayoutServerLoad = ({ locals: { preview } }) => {
  return { preview }
}

Client Layout (src/routes/+layout.ts):

import { setPreviewing } from '@sanity/svelte-loader'
import type { LayoutLoad } from './$types'

export const load: LayoutLoad = ({ data: { preview } }) => {
  setPreviewing(preview)
}

4. Data Fetching (Loaders)

Use locals.loadQuery in your page server loaders.

// src/routes/[slug]/+page.server.ts
import type { PageServerLoad } from './$types'

export const load: PageServerLoad = async ({ locals: { loadQuery }, params }) => {
  const initial = await loadQuery(QUERY, params)
  return { initial }
}

5. Real-time Preview & Visual Editing

Component Usage (useQuery)

Use useQuery in your Svelte component to handle real-time updates.

<!-- src/routes/[slug]/+page.svelte -->
<script lang="ts">
  import { useQuery } from '@sanity/svelte-loader'
  import type { PageData } from './$types'

  export let data: PageData
  const { initial } = data

  // Hydrate with initial data
  const query = useQuery(initial)

  // Reactive data access
  $: ({ data: post, loading, encodeDataAttribute } = $query)
</script>

{#if !loading && post}
  <!-- Use encodeDataAttribute for overlays -->
  <h1 data-sanity={encodeDataAttribute('title')}>
    {post.title}
  </h1>
{/if}

Enable Visual Editing (+layout.svelte)

Enable Visual Editing and Live Mode in your root layout.

<script lang="ts">
  import { useLiveMode } from '@sanity/svelte-loader'
  import { enableVisualEditing } from '@sanity/visual-editing'
  import { PUBLIC_SANITY_STUDIO_URL } from '$env/static/public'
  import { onMount } from 'svelte'

  onMount(() => enableVisualEditing())

  onMount(() => useLiveMode({
    studioUrl: PUBLIC_SANITY_STUDIO_URL
  }))
</script>

<slot />