SvelteKit Integration Guide
This guide provides resources and information for integrating Sveltia CMS with SvelteKit, a framework for building web applications using Svelte.
Examples
See real-world examples of SvelteKit integrations in our Showcase. Most of the listed sites include links to their source code, so you can explore how they implemented Sveltia CMS with SvelteKit.
Setup
Adding the Admin Page
SvelteKit serves static files from the static folder. Create static/admin/index.html and static/admin/config.yml as described in the Getting Started guide.
The Vite development server doesn’t serve index.html for a folder path in static, so open /admin/index.html instead of /admin/ during development. On a site built with adapter-static, most hosting services serve the admin page at /admin/ as usual.
Linking to the Admin Page
The admin page is not a SvelteKit route. Add the data-sveltekit-reload attribute to links to it, so they are opened as regular pages instead of being handled by the client-side router:
<a href="/admin/" data-sveltekit-reload>Edit content</a>Configuration
SvelteKit doesn’t have a built-in content folder, so Markdown files can be stored anywhere in the project, such as src/posts. The following example manages blog posts in that folder and stores images in the static folder:
media_folder: static/images
public_folder: /images
collections:
- name: posts
label: Posts
folder: src/posts
create: true
fields:
- { name: title, label: Title }
- { name: date, label: Date, widget: datetime }
- { name: description, label: Description, required: false }
- { name: body, label: Body, widget: markdown }Loading Content
A key step in integrating Sveltia CMS with SvelteKit is using Vite’s glob import to load all your content files at once in +layout.js or somewhere else in your SvelteKit app. Since SvelteKit uses Vite under the hood, you can take advantage of the import.meta.glob function without additional configuration. This allows you to easily access and manage your content within the SvelteKit framework.
Since content files are bundled with your site, the site must be rebuilt to reflect content changes made in the CMS. Most hosting services rebuild the site automatically when a commit is pushed to the repository.
Serving the CMS as a SvelteKit Route
The standard setup is to place index.html and config.yml in the static/admin folder as described in the Setup section above, but if you’re using the NPM package, you can also serve the CMS from a regular SvelteKit route. This is useful when you want to bundle the CMS with your site instead of loading it from a CDN, or define the configuration in JavaScript/TypeScript so it can be shared with your site’s content schemas or switched between a real and a test repository depending on the environment.
Sveltia CMS is a client-side single-page application that needs the window and document objects, so it can’t be rendered on the server. Disable SSR for the admin route by exporting ssr = false from its +page.js (or +page.ts) file; otherwise you’ll see an error like “Cannot read properties of undefined (reading 'bind')” during server-side rendering. The rest of your site can still be server-rendered or built as static pages as usual.
src/routes/admin/+page.ts:
export const ssr = false;src/routes/admin/+page.svelte:
<script lang="ts">
import CMS from '@sveltia/cms';
import { config } from '$lib/cms-config';
CMS.init({ config: { load_config_file: false, ...config } });
</script>
<svelte:head>
<meta name="robots" content="noindex" />
<title>Sveltia CMS</title>
</svelte:head>
<div id="nc-root"></div>src/lib/cms-config.ts:
import type { CmsConfig } from '@sveltia/cms';
export const config: CmsConfig = {
backend: {
name: 'github',
repo: 'owner/repo',
},
media_folder: 'static/uploads',
public_folder: '/uploads',
collections: [
// ...
],
};Some notes on this setup:
load_config_file: falsetells the CMS not to fetchconfig.yml, since the configuration is passed directly toinit(). Omit it if you’d rather keepconfig.ymlin thestaticfolder and only override some options.- The
<div id="nc-root">is a custom mount element. It keeps the CMS scoped to the page so your site’s layout doesn’t interfere with it. If the admin route has its own layout group that doesn’t load any of your site’s CSS, JavaScript or HTML, you can drop the wrapper and let the CMS mount to<body>as it normally does. - The
noindexmeta tag prevents the admin page from being indexed by search engines.
This approach was shared in a community discussion and should work similarly with other frameworks that let you turn off SSR per page, such as Astro.