- Integrations
Use SvelteKit with Prismic
Learn how to build websites with SvelteKit and Prismic.
Overview
Prismic has a first-party SvelteKit integration that supports all of Prismic’s features:
Build pages using slices and page types.
Write content alongside live previews.
Preview pages before publishing with full-website previews.
Model content with Slice Machine.
Fetch and display Prismic content using SDKs.
Code with confidence using generated TypeScript types.
Write content in multiple languages with locales.
Your favorite SvelteKit features are also supported:
Use the latest releases of Svelte 5 and SvelteKit 2.
Fetch content using
load
functions.Serve performant pages using prerendering.
Optimize images using imgix’s image CDN.
Set up a SvelteKit website
Prismic can be added to new or existing SvelteKit websites. Follow these steps to set up a SvelteKit project.
Create a Prismic repository
From the Prismic dashboard, create a Prismic repository. Select SvelteKit.
The Prismic dashboard where you can create a new repository.
When asked to select a starter, select Connect your own web app.
Set up a SvelteKit project
Follow the setup instructions shown in your Prismic repository.
Project setup steps in a Prismic repository.
The instructions guide you through creating a new SvelteKit project (if needed) and adding Prismic using
@slicemachine/init
.The
@slicemachine/init
command performs the following:Installs Slice Machine,
@prismicio/svelte
, and@prismicio/client
.Sets up content previews by creating an endpoint at
/api/preview
, a[[preview=preview]]
route directory, a root+layout.ts
file, and a root+layout.server.ts
file.Sets up live previews by creating a page at
/slice-simulator
.Creates a Prismic client at
$lib/prismicio.ts
.Saves Slice Machine configuration at
slicemachine.config.json
.
Model page content
Content modeling is the process of converting page designs into structured fields. We recommend adding support for a homepage and general pages.
See the Recommended models guide for instructions.
Set up content previews
Content writers can preview content on your website before publishing.
See the Live previews and Preview draft content sections for instructions.
Deploy your website
Before content writers can collaborate on the website, you’ll need to host it online.
See the Deploy section for instructions.
Publish content
Your SvelteKit website is now set up and ready for content. Visit your Prismic repository to build pages.
To recap, you completed the following:
Created a Prismic repository to store your website’s content.
Set up a SvelteKit project and integrated Prismic.
Prepared your website for a homepage and general pages.
Added support for live and full-website previews.
Deployed your website to your hosting provider.
Continue adding slices and other content models as you develop your website.
Create pages
Website pages are managed in Prismic using page types. Page types are created in Slice Machine.
Learn how to model pages and create SvelteKit page files in the Content Modeling guide. In the guide, you’ll find code snippets to bootstrap your pages.
Define routes
Prismic needs to know your website’s routes to fill in link URLs. Configure the routes
constant in your project’s $lib/prismicio.ts
with a set of route resolvers.
This example includes routes for a homepage, general pages, and a blog.
// `type` is the API ID of a page type.
// `path` determines the URL for a page of that type.
const routes: Routes[] = [
{ type: "homepage", path: "/" },
{ type: "page", path: "/:uid" },
{ type: "blog_post", path: "/blog/:uid" },
];
Your route resolvers should match your SvelteKit file-system-based routes. Here are some commonly used routes:
Route resolver path | SvelteKit file-system route |
---|---|
/ | src/routes/[[preview=preview]]/+page.svelte |
/:uid | src/routes/[[preview=preview]]/[uid]/+page.svelte |
/blog/:uid | src/routes/[[preview=preview]]/blog/[uid]/+page.svelte |
/:grandparent/:parent/:uid | src/routes/[[preview=preview]]/[...path]/+page.svelte |
Create slices
Page content is written using reusable page sections called slices. Slices are created in Slice Machine.
Write Svelte components
Slice Machine generates a bootstrapped Svelte component when a slice is created. You can find the generated files in src/lib/slices
or whichever slice library was selected.
Once your slice is configured with fields, edit the slice’s index.svelte
file to display the slice’s content.
Here is an example of a Call to Action slice. It displays some text and a link using a rich text and link field.
<script lang="ts">
import type { Content } from "@prismicio/client";
import { PrismicRichText, PrismicLink } from "@prismicio/svelte";
export let slice: Content.TextSlice;
</script>
<section className="flex flex-col gap-4 p-8">
<PrismicRichText field={slice.primary.text} />
<PrismicLink field={slice.primary.link} className="button" />
</section>
Fetch content
Use @prismicio/client
and its methods to fetch page content.
Set up a Prismic client
Create a $lib/prismicio.ts
file to centralize your Prismic client setup.
This file contains route resolvers and default Prismic client settings.
import {
createClient as baseCreateClient,
type Route,
} from "@prismicio/client";
import {
enableAutoPreviews,
type CreateClientConfig,
} from "@prismicio/svelte/kit";
import sm from "../../slicemachine.config.json";
export const repositoryName = sm.repositoryName;
// TODO: Update with your route resolvers.
const routes: Route[] = [
{ type: "homepage", path: "/" },
{ type: "page", path: "/:uid" },
{ type: "blog_post", path: "/blog/:uid" },
];
export function createClient({ cookies, ...config }: CreateClientConfig = {}) {
const client = prismic.createClient(repositoryName, {
routes,
...config,
});
enableAutoPreviews({ client, cookies });
return client;
}
Fetch content in pages and slices
Import createClient()
from $lib/prismicio.ts
and create a client. Use the client to fetch content.
This example page fetches content for a /[uid]
dynamic route.
import { createClient } from "$lib/prismicio";
export async function load({ params, fetch, cookies }) {
const client = createClient({ fetch, cookies });
const page = await client.getByUID("page", params.uid);
return { page };
}
We do not recommend fetching content in slices on the client. Instead, you can use a content relationship field to fetch linked content. You can also use <SliceZone>
’s context
prop to pass arbitary data from a page to a slice.
Display content
Prismic content can be displayed using @prismicio/svelte
.
Here are the most commonly used components in SvelteKit websites:
<PrismicLink>
- Display links.<PrismicImage>
- Display images.<PrismicRichText>
- Display rich text.<PrismicText>
- Display plain text.<SliceZone>
- Display slices.
Live previews in the Page Builder
Content writers can preview content live while editing in the Page Builder. Each slice in a page is shown as a live-updating thumbnail.
A page with live previews in the Page Builder.
Set up live previewing
Live previews require a special /slice-simulator
route in your SvelteKit website.
Create a page at
/slice-simulator
Create a file at
src/routes/slice-simulator/+page.svelte
with the following contents.src/routes/slice-simulator/+page.svelte<script> import { SliceSimulator } from "@slicemachine/adapter-sveltekit/simulator"; import { SliceZone } from "@prismicio/svelte"; import { components } from "$lib/slices"; </script> <SliceSimulator let:slices> <SliceZone {slices} {components} /> </SliceSimulator>
Set the simulator URL in the Page Builder
Navigate to your Prismic repository and open a document.
Click the ”…” button next to the Publish/Unpublish button in the top-right corner. Select Live preview settings.
The live preview settings menu option.
In the modal, enter
http://localhost:5173/slice-simulator
and click Save.
Preview draft content
Content writers can preview content on your website before publishing.
@slicemachine/init
performs most of the setup for you during project setup. However, there are a few steps to complete manually.
Set up previews in SvelteKit
@prismicio/svelte
provides helpers and a component to support content previews.
Add
<PrismicPreview>
tosrc/routes/+layout.svelte
<PrismicPreview>
adds the Prismic toolbar and event listeners. The website automatically refreshes when a content draft is saved.src/routes/+layout.svelte<script> import { PrismicPreview } from "@prismicio/svelte/kit"; import { repositoryName } from "$lib/prismicio"; </script> <main> <slot /> </main> <PrismicPreview {repositoryName} />
Call
enableAutoPreviews()
with your Prismic clientenableAutoPreviews()
configures a Prismic client to automatically fetch draft content during a preview. Include it in your$lib/prismicio.ts
file.src/lib/prismicio.tsimport { createClient as baseCreateClient } from "@prismicio/client"; import { type CreateClientConfig, enableAutoPreviews, } from "@prismicio/svelte/kit"; import sm from "../slicemachine.config.json"; export const repositoryName = sm.repositoryName; export function createClient({ cookies, ...config }: CreateClientConfig = {}) { const client = baseCreateClient(repositoryName, config); enableAutoPreviews({ client, cookies }); return client; }
Create an
/api/preview
endpointThis endpoint enables content previews and redirects a content writer to the previewed document. It uses
redirectToPreviewURL()
.src/routes/api/preview/+server.tsimport { redirectToPreviewURL } from "@prismicio/svelte/kit"; import { createClient } from "$lib/prismicio"; export async function GET({ fetch, request, cookies }) { const client = createClient({ fetch }); return await redirectToPreviewURL({ client, request, cookies }); }
Create a
preview
route matcherThis route matcher tells SvelteKit when to fetch draft content and dynamically render a page during content previews. It matches routes prefixed with
/preview
(e.g./preview/about
).Create a file at
src/params/preview.ts
with the following contents.src/params/preview.tsexport function match(param) { return param === "preview"; }
Create a
[[preview=preview]]
route parameterThis route parameter optionally prefixes routes with
/preview
. It uses thepreview
route matcher created in the previous step.Create a directory at
src/routes/[[preview=preview]]
. Nest all page routes within it.Configure
prerender
toauto
Setting the
prerender
page option toauto
tells SvelteKit to prerender all pages it knows about.Because SvelteKit does not know about routes prefixed with
/preview
(e.g./preview/about
), routes prefixed with/preview
are not prerendered.Create a file at
src/routes/+layout.server.ts
with the following contents.src/routes/+layout.server.tsexport const prerender = "auto";
Set up previews in Prismic
After setting up previews in your SvelteKit project, set up previews in Prismic.
Open your preview settings
Navigate to your Prismic repository and go to Settings > Previews.
The previews settings page.
Create a preview
In the Manage your previews section, create a preview using the following values:
Field Value Site name Development Domain for your application http://localhost:5173
Preview route /api/preview
Click Create my preview.
Deploy
To deploy your website, follow the instructions for deploying SvelteKit with your chosen hosting provider:
Handle content changes
Your app needs to be rebuilt when your content changes in Prismic.
Follow the instructions in our webhooks documentation for your hosting provider.
SEO
Prismic websites can be optimized for search engines using meta_title
and meta_descriptions
fields. These fields provide metadata and improve your website’s ranking.
Add SEO fields to your page types
SEO fields are added to page types by default in an SEO tab.
If your page type does not have this tab, create a tab named SEO and add the following fields:
Label API ID Type Description Meta Title meta_title
Rich Text The title shown in search results. Meta Description meta_description
Text The description shown in search results. Meta Image meta_image
Image The image shown in link previews. The
meta_image
field is not typically used by search engines, but it can be used as a preview when linking to your website on some platforms.Add metadata to pages
Use the metadata fields in a
+page.svelte
’s<svelte:head>
.src/routes/[[preview=preview]]/[uid]/+page.svelte<svelte:head> <title>{page.data.meta_title}</title> {#if isFilled.keyText(page.data.meta_description)} <meta name="description" content={page.data.meta_description} /> {/if} {#if isFilled.image(page.data.meta_image)} <meta property="og:image" content={asImageSrc(page.data.meta_image)} /> {/if} </svelte:head>
Internationalization
Prismic supports websites with multiple languages.
Install the necessary packages
The
negotiator
and@formatjs/intl-localematcher
packages are needed to support internationalization.npm install negotiator @formatjs/intl-localematcher
Create a
$lib/i18n.ts
fileThe
$lib/i18n.ts
file provides a set of internationalization helpers. The helpers will be used in your website’shandle
hook.Create a
$lib/i18n.ts
file with the following contents.src/lib/i18n.tsimport { redirect, type RequestEvent } from "@sveltejs/kit"; import { match } from "@formatjs/intl-localematcher"; import Negotiator from "negotiator"; /** * A record of locales mapped to a version displayed in URLs. The first entry is * used as the default locale. */ // TODO: Update this object with your website's supported locales. Keys // should be the locale IDs registered in your Prismic repository, and values // should be the string that appears in the URL. const LOCALES: Record<string, string> = { "en-us": "en-us", "fr-fr": "fr-fr", }; /** Redirects with an auto-detected locale prepended to the URL. */ export function redirectToLocale(event: RequestEvent) { const headers = { "accept-language": event.request.headers.get("accept-language") ?? undefined, }; const languages = new Negotiator({ headers }).languages(); const locales = Object.keys(LOCALES); const locale = match(languages, locales, locales[0]); const destination = new URL(event.url); destination.pathname = `/${LOCALES[locale]}${event.url.pathname}`; redirect(302, destination); } /** Determines if a pathname has a locale as its first segment. */ export function pathnameHasLocale(event: RequestEvent): boolean { const regexp = new RegExp(`^/(${Object.values(LOCALES).join("|")})(/|$)`); return regexp.test(event.url.pathname); } /** * Returns the full locale of a given locale. It returns `undefined` if the * locale is not in the master list. */ export function reverseLocaleLookup(locale: string): string | undefined { for (const key in LOCALES) { if (LOCALES[key] === locale) { return key; } } }
Define locales in
$lib/i18n.ts
$lib/i18n.ts
contains a list of locales supported by your website.Update the
LOCALES
constant to match your Prismic repository’s locales. The first locale is used when a visitor’s locale is not supported.src/lib/i18n.tsconst LOCALES = { "en-us": "en-us", "fr-fr": "fr-fr", };
You can define how the locale appears in the URL by changing the object’s values. In the following example, the
en-us
locale will appear asen
in the URL (e.g./en/about
).src/lib/i18n.tsconst LOCALES = { "en-us": "en", "fr-fr": "fr", };
Create or modify
hooks.server.ts
Website visitors will be directed to the correct locale using
handle
insrc/hooks.server.ts
.Create a
src/hooks.server.ts
file with the following contents, or modify your existingsrc/hooks.server.ts
to include the highlighted lines.src/hooks.server.tsimport { type Handle } from "@sveltejs/kit"; import { pathnameHasLocale, redirectToLocale } from "$lib/i18n"; export const handle: Handle = async ({ event, resolve }) => { if (!pathnameHasLocale(event)) { redirectToLocale(event); } return resolve(event); };
Nest routes under a
[lang]
dynamic route segmentCreate a directory at
src/routes/[[preview=preview]]/[lang]
and nest all other routes under this directory.The
lang
route parameter will contain the visitor’s locale. For example,/en-us/about
setslang
to"en-us"
.Fetch content from the visitor’s locale
In your
+page.server.ts
files, forward thelang
parameter to your Prismic query.src/routes/[[preview=preview]]/[lang]/[uid]/+page.server.tsimport { createClient } from "$lib/prismicio"; import { reverseLocaleLookup } from "$lib/i18n"; export async function load({ params, fetch, cookies }) { const client = createClient({ fetch, cookies }); const page = await client.getByUID("page", params.uid, { lang: reverseLocaleLookup(params.lang), }); // ... }
The
reverseLocaleLookup
helper from$lib/i18n.ts
converts a shortened locale (e.g.en
) to its full version (e.g.en-us
).Fetch all locales in
entries
Fetch documents from all locales using the Prismic client’s
lang: "*"
option. Include thelang
route parameter.src/routes/[[preview=preview]]/[lang]/[uid]/+page.server.tsexport async function entries() { const client = createClient(); const pages = await client.getAllByType("page", { lang: "*", }); return pages.map((page) => { return { lang: page.lang, uid: page.uid, }; }); }
Configure Slice Machine
Slice Machine can be configured in slicemachine.config.json
. Add options to the adapter.options
property.
{
"repositoryName": "example-prismic-repo",
"libraries": ["./src/slices"],
"localSliceSimulatorURL": "http://localhost:5173/slice-simulator",
"adapter": {
"resolve": "@slicemachine/adapter-sveltekit",
"options": {
"typescript": true
}
}
}
Property | Description | Default |
---|---|---|
format optional | boolean Determines if generated files are formatted using Prettier. | true |
typescript optional | boolean Determines if generated files are written in TypeScript or JavaScript.
Defaults to | |
generatedTypesFilePath optional | string The filepath at which generated TypeScript types will be saved. | src/prismicio-types.d.ts |
environmentVariableFilePath optional | string The filepath at which the active Prismic environment is stored as an environment variable. | .env.local |