Documentation
Introduction permalink
Before we begin
SvelteKit is in early development, and some things may change before we hit version 1.0. This document is a work-in-progress. If you get stuck, reach out for help in the Discord chatroom.
See the migration guides for help upgrading from Sapper.
What is SvelteKit?
SvelteKit is a framework for building extremely high-performance web apps.
Building an app with all the modern best practices is fiendishly complicated. Those practices include build optimizations, so that you load only the minimal required code; offline support; prefetching pages before the user initiates navigation; and configurable rendering that allows you to generate HTML on the server or in the browser at runtime or at build-time. SvelteKit does all the boring stuff for you so that you can get on with the creative part.
It uses Vite with a Svelte plugin to provide a lightning-fast and feature-rich development experience with Hot Module Replacement (HMR), where changes to your code are reflected in the browser instantly.
You don't need to know Svelte to understand the rest of this guide, but it will help. In short, it's a UI framework that compiles your components to highly optimized vanilla JavaScript. Read the introduction to Svelte blog post and the Svelte tutorial to learn more.
Getting started
The easiest way to start building a SvelteKit app is to run npm init
:
npm init svelte@next my-app
cd my-app
npm install
npm run dev
The first command will scaffold a new project in the my-app
directory asking you if you'd like to setup some basic tooling such as TypeScript. See the FAQ for pointers on setting up additional tooling. The subsequent commands will then install its dependencies and start a server on localhost:3000.
There are two basic concepts:
- Each page of your app is a Svelte component
- You create pages by adding files to the
src/routes
directory of your project. These will be server-rendered so that a user's first visit to your app is as fast as possible, then a client-side app takes over
Try editing the files to get a feel for how everything works – you may not need to bother reading the rest of this guide!
Editor setup
We recommend using Visual Studio Code (aka VS Code) with the Svelte extension, but support also exists for numerous other editors.
Routing permalink
At the heart of SvelteKit is a filesystem-based router. This means that the structure of your application is defined by the structure of your codebase — specifically, the contents of src/routes
.
You can change this to a different directory by editing the project config.
There are two types of route — pages and endpoints.
Pages typically generate HTML to display to the user (as well as any CSS and JavaScript needed for the page). By default, pages are rendered on both the client and server, though this behaviour is configurable.
Endpoints run only on the server (or when you build your site, if prerendering). This means it's the place to do things like access databases or APIs that require private credentials or return data that lives on a machine in your production network. Pages can request data from endpoints. Endpoints return JSON by default, though may also return data in other formats.
Pages
Pages are Svelte components written in .svelte
files (or any file with an extension listed in config.extensions
). By default, when a user first visits the application, they will be served a server-rendered version of the page in question, plus some JavaScript that 'hydrates' the page and initialises a client-side router. From that point forward, navigating to other pages is handled entirely on the client for a fast, app-like feel where the common portions in the layout do not need to be rerendered.
The filename determines the route. For example, src/routes/index.svelte
is the root of your site:
<!-- src/routes/index.svelte -->
<svelte:head>
<title>Welcome</title>
</svelte:head>
<h1>Hello and welcome to my site!</h1>
A file called either src/routes/about.svelte
or src/routes/about/index.svelte
would correspond to the /about
route:
<!-- src/routes/about.svelte -->
<svelte:head>
<title>About</title>
</svelte:head>
<h1>About this site</h1>
<p>TODO...</p>
Dynamic parameters are encoded using [brackets]
. For example, a blog post might be defined by src/routes/blog/[slug].svelte
.
A file or directory can have multiple dynamic parts, like [id]-[category].svelte
. (Parameters are 'non-greedy'; in an ambiguous case like x-y-z
, id
would be x
and category
would be y-z
.)
Endpoints
Endpoints are modules written in .js
(or .ts
) files that export functions corresponding to HTTP methods. Their job is to allow pages to read and write data that is only available on the server (for example in a database, or on the filesystem).
// Type declarations for endpoints (declarations marked with
// an `export` keyword can be imported from `@sveltejs/kit`)
export interface RequestHandler<Output = Record<string, any>> {
(event: RequestEvent): MaybePromise<
Either<Output extends Response ? Response : EndpointOutput<Output>, Fallthrough>
>;
}
export interface RequestEvent {
request: Request;
url: URL;
params: Record<string, string>;
locals: App.Locals;
platform: App.Platform;
}
export interface EndpointOutput<Output = Record<string, any>> {
status?: number;
headers?: Headers | Partial<ResponseHeaders>;
body?: Record<string, any>;
}
type MaybePromise<T> = T | Promise<T>;
interface Fallthrough {
fallthrough: true;
}
See the TypeScript section for information on
App.Locals
andApp.Platform
.
A page like src/routes/items/[id].svelte
could get its data from src/routes/items/[id].js
:
import db from '$lib/database';
/** @type {import('@sveltejs/kit').RequestHandler} */
export async function get({ params }) {
// `params.id` comes from [id].js
const item = await db.get(params.id);
if (item) {
return {
body: { item }
};
}
return {
status: 404
};
}
All server-side code, including endpoints, has access to
fetch
in case you need to request data from external APIs. Don't worry about the$lib
import, we'll get to that later.
The job of this function is to return a { status, headers, body }
object representing the response, where status
is an HTTP status code:
2xx
— successful response (default is200
)3xx
— redirection (should be accompanied by alocation
header)4xx
— client error5xx
— server error
If
{fallthrough: true}
is returned SvelteKit will fall through to other routes until something responds, or will respond with a generic 404.
The returned body
corresponds to the page's props:
<script>
// populated with data from the endpoint
export let item;
</script>
<h1>{item.title}</h1>
POST, PUT, PATCH, DELETE
Endpoints can handle any HTTP method — not just GET
— by exporting the corresponding function:
export function post(event) {...}
export function put(event) {...}
export function patch(event) {...}
export function del(event) {...} // `delete` is a reserved word
These functions can, like get
, return a body
that will be passed to the page as props. Whereas 4xx/5xx responses from get
will result in an error page rendering, similar responses to non-GET requests do not, allowing you to do things like render form validation errors:
// src/routes/items.js
import * as db from '$lib/database';
export async function get() {
const items = await db.list();
return {
body: { items }
};
}
export async function post({ request }) {
const [errors, item] = await db.create(request);
if (errors) {
// return validation errors
return {
status: 400,
body: { errors }
};
}
// redirect to the newly created item
return {
status: 303,
headers: {
location: `/items/${item.id}`
}
};
}
<!-- src/routes/items.svelte -->
<script>
// The page always has access to props from `get`...
export let items;
// ...plus props from `post` when the page is rendered
// in response to a POST request, for example after
// submitting the form below
export let errors;
</script>
{#each items as item}
<Preview item={item}/>
{/each}
<form method="post">
<input name="title">
{#if errors?.title}
<p class="error">{errors.title}</p>
{/if}
<button type="submit">Create item</button>
</form>
If you request the route with an accept: application/json
header, SvelteKit will render the endpoint data as JSON, rather than the page as HTML.
Body parsing
The request
object is an instance of the standard Request class. As such, accessing the request body is easy:
export async function post({ request }) {
const data = await request.formData(); // or .json(), or .text(), etc
}
Setting cookies
Endpoints can set cookies by returning a headers
object with set-cookie
. To set multiple cookies simultaneously, return an array:
return {
headers: {
'set-cookie': [cookie1, cookie2]
}
};
HTTP method overrides
HTML <form>
elements only support GET
and POST
methods natively. You can allow other methods, like PUT
and DELETE
, by specifying them in your configuration and adding a _method=VERB
parameter (you can configure the name) to the form's action
:
// svelte.config.js
export default {
kit: {
methodOverride: {
allowed: ['PUT', 'PATCH', 'DELETE']
}
}
};
<form method="post" action="/todos/{id}?_method=PUT">
<!-- form elements -->
</form>
Using native
<form>
behaviour ensures your app continues to work when JavaScript fails or is disabled.
Standalone endpoints
Most commonly, endpoints exist to provide data to the page with which they're paired. They can, however, exist separately from pages. Standalone endpoints have slightly more flexibility over the returned body
type — in addition to objects, they can return a string or a Uint8Array
.
Support for streaming request and response bodies is coming soon.
Private modules
Files and directories with a leading _
or .
(other than .well-known
) are private by default, meaning that they do not create routes (but can be imported by files that do). You can configure which modules are considered public or private with the routes
configuration.
Advanced routing
Rest parameters
A route can have multiple dynamic parameters, for example src/routes/[category]/[item].svelte
or even src/routes/[category]-[item].svelte
. (Parameters are 'non-greedy'; in an ambiguous case like /x-y-z
, category
would be x
and item
would be y-z
.) If the number of route segments is unknown, you can use rest syntax — for example you might implement GitHub's file viewer like so...
/[org]/[repo]/tree/[branch]/[...file]
...in which case a request for /sveltejs/kit/tree/master/documentation/docs/01-routing.md
would result in the following parameters being available to the page:
{
org: 'sveltejs',
repo: 'kit',
branch: 'master',
file: 'documentation/docs/01-routing.md'
}
src/routes/a/[...rest]/z.svelte
will match/a/z
as well as/a/b/z
and/a/b/c/z
and so on. Make sure you check that the value of the rest parameter is valid.
Fallthrough routes
Finally, if you have multiple routes that match a given path, SvelteKit will try each of them until one responds. For example if you have these routes...
src/routes/[baz].js
src/routes/[baz].svelte
src/routes/[qux].svelte
src/routes/foo-[bar].svelte
... and you navigate to /foo-xyz
, then SvelteKit will first try foo-[bar].svelte
because it is the best match. If that yields no response, SvelteKit will try other less specific yet still valid matches for /foo-xyz
. Since endpoints have higher precedence than pages, the next attempt will be [baz].js
. Then alphabetical order takes precedence and thus [baz].svelte
will be tried before [qux].svelte
. The first route that responds — a page that returns something from load
or has no load
function, or an endpoint that returns something — will handle the request.
If no page or endpoint responds to a request, SvelteKit will respond with a generic 404.
Layouts permalink
So far, we've treated pages as entirely standalone components — upon navigation, the existing component will be destroyed, and a new one will take its place.
But in many apps, there are elements that should be visible on every page, such as top-level navigation or a footer. Instead of repeating them in every page, we can use layout components.
To create a layout component that applies to every page, make a file called src/routes/__layout.svelte
. The default layout component (the one that SvelteKit uses if you don't bring your own) looks like this...
<slot></slot>
...but we can add whatever markup, styles and behaviour we want. The only requirement is that the component includes a <slot>
for the page content. For example, let's add a nav bar:
<!-- src/routes/__layout.svelte -->
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/settings">Settings</a>
</nav>
<slot></slot>
If we create pages for /
, /about
and /settings
...
<!-- src/routes/index.svelte -->
<h1>Home</h1>
<!-- src/routes/about.svelte -->
<h1>About</h1>
<!-- src/routes/settings.svelte -->
<h1>Settings</h1>
...the nav will always be visible, and clicking between the three pages will only result in the <h1>
being replaced.
Nested layouts
Suppose we don't just have a single /settings
page, but instead have nested pages like /settings/profile
and /settings/notifications
with a shared submenu (for a real-life example, see github.com/settings).
We can create a layout that only applies to pages below /settings
(while inheriting the root layout with the top-level nav):
<!-- src/routes/settings/__layout.svelte -->
<h1>Settings</h1>
<div class="submenu">
<a href="/settings/profile">Profile</a>
<a href="/settings/notifications">Notifications</a>
</div>
<slot></slot>
Resets
To reset the layout stack, create a __layout.reset.svelte
file instead of a __layout.svelte
file. For example, if you want your /admin/*
pages to not inherit the root layout, create a file called src/routes/admin/__layout.reset.svelte
.
Layout resets are otherwise identical to normal layout components.
Error pages
If a page fails to load (see Loading), SvelteKit will render an error page. You can customise this page by creating __error.svelte
components alongside your layout and page components.
For example, if src/routes/settings/notifications/index.svelte
failed to load, SvelteKit would render src/routes/settings/notifications/__error.svelte
in the same layout, if it existed. If not, it would render src/routes/settings/__error.svelte
in the parent layout, or src/routes/__error.svelte
in the root layout.
SvelteKit provides a default error page in case you don't supply
src/routes/__error.svelte
, but it's recommended that you bring your own.
// declaration type
// * also see type for `LoadOutput` in the Loading section
export interface ErrorLoadInput<Params extends Record<string, string> = Record<string, string>>
extends LoadInput<Params> {
status?: number;
error?: Error;
}
If an error component has a load
function, it will be called with error
and status
properties:
<script context="module">
/** @type {import('@sveltejs/kit').ErrorLoad} */
export function load({ error, status }) {
return {
props: {
title: `${status}: ${error.message}`
}
};
}
</script>
<script>
export let title;
</script>
<h1>{title}</h1>
Layout components also have access to
error
andstatus
via the page storeServer-side stack traces will be removed from
error
in production, to avoid exposing privileged information to users.
Loading permalink
A component that defines a page or a layout can export a load
function that runs before the component is created. This function runs both during server-side rendering and in the client, and allows you to fetch and manipulate data before the page is rendered, thus preventing loading spinners.
If the data for a page comes from its endpoint, you may not need a load
function. It's useful when you need more flexibility, for example loading data from an external API.
// Type declarations for `load` (declarations marked with
// an `export` keyword can be imported from `@sveltejs/kit`)
export interface Load<Params = Record<string, string>, Props = Record<string, any>> {
(input: LoadInput<Params>): MaybePromise<Either<Fallthrough, LoadOutput<Props>>>;
}
export interface LoadInput<Params extends Record<string, string> = Record<string, string>> {
url: URL;
params: Params;
props: Record<string, any>;
fetch(info: RequestInfo, init?: RequestInit): Promise<Response>;
session: App.Session;
stuff: Partial<App.Stuff>;
}
export interface LoadOutput<Props extends Record<string, any> = Record<string, any>> {
status?: number;
error?: string | Error;
redirect?: string;
props?: Props;
stuff?: Partial<App.Stuff>;
maxage?: number;
}
type MaybePromise<T> = T | Promise<T>;
interface Fallthrough {
fallthrough: true;
}
See the TypeScript section for information on
App.Session
andApp.Stuff
.
A page that loads data from an external API might look like this:
<!-- src/routes/blog/[slug].svelte -->
<script context="module">
/** @type {import('@sveltejs/kit').Load} */
export async function load({ params, fetch, session, stuff }) {
const response = await fetch(`https://cms.example.com/article/${params.slug}.json`);
return {
status: response.status,
props: {
article: response.ok && (await response.json())
}
};
}
</script>
Note the
<script context="module">
— this is necessary becauseload
runs before the component is rendered. Code that is per-component instance should go into a second<script>
tag.
load
is similar to getStaticProps
or getServerSideProps
in Next.js, except that it runs on both the server and the client. In the example above, if a user clicks on a link to this page the data will be fetched from cms.example.com
without going via our server.
If load
returns {fallthrough: true}
, SvelteKit will fall through to other routes until something responds, or will respond with a generic 404.
SvelteKit's load
receives an implementation of fetch
, which has the following special properties:
- it has access to cookies on the server
- it can make requests against the app's own endpoints without issuing an HTTP call
- it makes a copy of the response when you use it, and then sends it embedded in the initial page load for hydration
load
only applies to page and layout components (not components they import), and runs on both the server and in the browser with the default rendering options.
Code called inside
load
blocks:
- should use the SvelteKit-provided
fetch
wrapper rather than using the nativefetch
- should not reference
window
,document
, or any browser-specific objects- should not directly reference any API keys or secrets, which will be exposed to the client, but instead call an endpoint that uses any required secrets
It is recommended that you not store pre-request state in global variables, but instead use them only for cross-cutting concerns such as caching and holding database connections.
Mutating any shared state on the server will affect all clients, not just the current one.
Input
The load
function receives an object containing six fields — url
, params
, props
, fetch
, session
and stuff
. The load
function is reactive, and will re-run when its parameters change, but only if they are used in the function. Specifically, if url
, session
or stuff
are used in the function, they will be re-run whenever their value changes, and likewise for the individual properties of params
.
Note that destructuring parameters in the function declaration is enough to count as using them.
url
url
is an instance of URL
, containing properties like the origin
, hostname
, pathname
and searchParams
.
In some environments this is derived from request headers, which you may need to configure, during server-side rendering
params
params
is derived from url.pathname
and the route filename.
For a route filename example like src/routes/a/[b]/[...c]
and a url.pathname
of /a/x/y/z
, the params
object would look like this:
{
"b": "x",
"c": "y/z"
}
props
If the page you're loading has an endpoint, the data returned from it is accessible inside the leaf component's load
function as props
. For layout components and pages without endpoints, props
will be an empty object.
fetch
fetch
is equivalent to the native fetch
web API, and can make credentialed requests. It can be used across both client and server contexts.
When
fetch
runs on the server, the resulting response will be serialized and inlined into the rendered HTML. This allows the subsequent client-sideload
to access identical data immediately without an additional network request.
Cookies will only be passed through if the target host is the same as the SvelteKit application or a more specific subdomain of it.
session
session
can be used to pass data from the server related to the current request, e.g. the current user. By default it is undefined
. See getSession
to learn how to use it.
stuff
stuff
is passed from layout components to child layouts and page components and can be filled with anything else you need to make available. For the root __layout.svelte
component, it is equal to {}
, but if that component's load
function returns an object with a stuff
property, it will be available to subsequent load
functions.
Output
If you return a Promise from load
, SvelteKit will delay rendering until the promise resolves. The return value has several properties, all optional:
status
The HTTP status code for the page. If returning an error
this must be a 4xx
or 5xx
response; if returning a redirect
it must be a 3xx
response. The default is 200
.
error
If something goes wrong during load
, return an Error
object or a string
describing the error alongside a 4xx
or 5xx
status code.
redirect
If the page should redirect (because the page is deprecated, or the user needs to be logged in, or whatever else) return a string
containing the location to which they should be redirected alongside a 3xx
status code.
The redirect
string should be a properly encoded URI. Both absolute and relative URIs are acceptable.
maxage
To cause pages to be cached, return a number
describing the page's max age in seconds. The resulting cache header will include private
if user data was involved in rendering the page (either via session
, or because a credentialed fetch
was made in a load
function), but otherwise will include public
so that it can be cached by CDNs.
This only applies to page components, not layout components.
props
If the load
function returns a props
object, the props will be passed to the component when it is rendered.
stuff
This will be merged with any existing stuff
and passed to the load
functions of subsequent layout and page components.
The combined stuff
is available to components using the page store as $page.stuff
, providing a mechanism for pages to pass data 'upward' to layouts.
Hooks permalink
An optional src/hooks.js
(or src/hooks.ts
, or src/hooks/index.js
) file exports four functions, all optional, that run on the server — handle, handleError, getSession, and externalFetch.
The location of this file can be configured as
config.kit.files.hooks
handle
This function runs every time SvelteKit receives a request — whether that happens while the app is running, or during prerendering — and determines the response. It receives an event
object representing the request and a function called resolve
, which invokes SvelteKit's router and generates a response (rendering a page, or invoking an endpoint) accordingly. This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing endpoints programmatically, for example).
Requests for static assets — which includes pages that were already prerendered — are not handled by SvelteKit.
If unimplemented, defaults to ({ event, resolve }) => resolve(event)
.
// Type declarations for `handle` (declarations marked with
// an `export` keyword can be imported from `@sveltejs/kit`)
export interface RequestEvent {
request: Request;
url: URL;
params: Record<string, string>;
locals: App.Locals;
platform: App.Platform;
}
export interface ResolveOpts {
ssr?: boolean;
}
export interface Handle {
(input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOpts): MaybePromise<Response>;
}): MaybePromise<Response>;
}
See the TypeScript section for information on
App.Locals
andApp.Platform
.
To add custom data to the request, which is passed to endpoints, populate the event.locals
object, as shown below.
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
event.locals.user = await getUserInformation(event.request.headers.get('cookie'));
const response = await resolve(event);
response.headers.set('x-custom-header', 'potato');
return response;
}
You can add call multiple handle
functions with the sequence
helper function.
resolve
also supports a second, optional parameter that gives you more control over how the response will be rendered. That parameter is an object that can have the following fields:
ssr
(boolean, defaulttrue
) — specifies whether the page will be loaded and rendered on the server.
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
const response = await resolve(event, {
ssr: !event.url.pathname.startsWith('/admin')
});
return response;
}
Disabling server-side rendering effectively turns your SvelteKit app into a single-page app or SPA. In most situations this is not recommended (see appendix). Consider whether it's truly appropriate to disable it, and do so selectively rather than for all requests.
handleError
If an error is thrown during rendering, this function will be called with the error
and the event
that caused it. This allows you to send data to an error tracking service, or to customise the formatting before printing the error to the console.
During development, if an error occurs because of a syntax error in your Svelte code, a frame
property will be appended highlighting the location of the error.
If unimplemented, SvelteKit will log the error with default formatting.
export interface HandleError {
(input: { error: Error & { frame?: string }; event: RequestEvent }): void;
}
/** @type {import('@sveltejs/kit').HandleError} */
export async function handleError({ error, event }) {
// example integration with https://sentry.io/
Sentry.captureException(error, { event });
}
handleError
is only called in the case of an uncaught exception. It is not called when pages and endpoints explicitly respond with 4xx and 5xx status codes.
getSession
This function takes the event
object and returns a session
object that is accessible on the client and therefore must be safe to expose to users. It runs whenever SvelteKit server-renders a page.
If unimplemented, session is {}
.
export interface GetSession {
(event: RequestEvent): MaybePromise<App.Session>;
}
/** @type {import('@sveltejs/kit').GetSession} */
export function getSession(event) {
return event.locals.user
? {
user: {
// only include properties needed client-side —
// exclude anything else attached to the user
// like access tokens etc
name: event.locals.user.name,
email: event.locals.user.email,
avatar: event.locals.user.avatar
}
}
: {};
}
session
must be serializable, which means it must not contain things like functions or custom classes, just built-in JavaScript data types
externalFetch
This function allows you to modify (or replace) a fetch
request for an external resource that happens inside a load
function that runs on the server (or during pre-rendering).
For example, your load
function might make a request to a public URL like https://api.yourapp.com
when the user performs a client-side navigation to the respective page, but during SSR it might make sense to hit the API directly (bypassing whatever proxies and load balancers sit between it and the public internet).
export interface ExternalFetch {
(req: Request): Promise<Response>;
}
/** @type {import('@sveltejs/kit').ExternalFetch} */
export async function externalFetch(request) {
if (request.url.startsWith('https://api.yourapp.com/')) {
// clone the original request, but change the URL
request = new Request(
request.url.replace('https://api.yourapp.com/', 'http://localhost:9999/'),
request
);
}
return fetch(request);
}
Modules permalink
SvelteKit makes a number of modules available to your application.
$app/env
import { amp, browser, dev, mode, prerendering } from '$app/env';
amp
istrue
orfalse
depending on the corresponding value in your project configurationbrowser
istrue
orfalse
depending on whether the app is running in the browser or on the serverdev
istrue
in development mode,false
in productionmode
is the Vite mode, which isdevelopment
in dev mode orproduction
during build unless configured otherwise inconfig.kit.vite.mode
.prerendering
istrue
when prerendering,false
otherwise
$app/navigation
import {
disableScrollHandling,
goto,
invalidate,
prefetch,
prefetchRoutes,
beforeNavigate,
afterNavigate
} from '$app/navigation';
afterNavigate(({ from, to }: { from: URL, to: URL }) => void)
- a lifecycle function that runs when the components mounts, and after subsequent navigations while the component remains mountedbeforeNavigate(({ from, to, cancel }: { from: URL, to: URL | null, cancel: () => void }) => void)
— a function that runs whenever navigation is triggered whether by clicking a link, callinggoto
, or using the browser back/forward controls. This includes navigation to external sites.to
will benull
if the user is closing the page. Callingcancel
will prevent the navigation from proceedingdisableScrollHandling
will, if called when the page is being updated following a navigation (inonMount
or an action, for example), prevent SvelteKit from applying its normal scroll management. You should generally avoid this, as breaking user expectations of scroll behaviour can be disorienting.goto(href, { replaceState, noscroll, keepfocus, state })
returns aPromise
that resolves when SvelteKit navigates (or fails to navigate, in which case the promise rejects) to the specifiedhref
. The second argument is optional:replaceState
(boolean, defaultfalse
) Iftrue
, will replace the currenthistory
entry rather than creating a new one withpushState
noscroll
(boolean, defaultfalse
) Iftrue
, the browser will maintain its scroll position rather than scrolling to the top of the page after navigationkeepfocus
(boolean, defaultfalse
) Iftrue
, the currently focused element will retain focus after navigation. Otherwise, focus will be reset to the bodystate
(object, default{}
) The state of the new/updated history entry
invalidate(href)
causes anyload
functions belonging to the currently active page to re-run if theyfetch
the resource in question. It returns aPromise
that resolves when the page is subsequently updated.prefetch(href)
programmatically prefetches the given page, which means a) ensuring that the code for the page is loaded, and b) calling the page'sload
function with the appropriate options. This is the same behaviour that SvelteKit triggers when the user taps or mouses over an<a>
element with sveltekit:prefetch. If the next navigation is tohref
, the values returned fromload
will be used, making navigation instantaneous. Returns aPromise
that resolves when the prefetch is complete.prefetchRoutes(routes)
— programmatically prefetches the code for routes that haven't yet been fetched. Typically, you might call this to speed up subsequent navigation. If no argument is given, all routes will be fetched; otherwise, you can specify routes by any matching pathname such as/about
(to matchsrc/routes/about.svelte
) or/blog/*
(to matchsrc/routes/blog/[slug].svelte
). Unlikeprefetch
, this won't callload
for individual pages. Returns aPromise
that resolves when the routes have been prefetched.
$app/paths
import { base, assets } from '$app/paths';
base
— a root-relative (i.e. begins with a/
) string that matchesconfig.kit.paths.base
, or the empty string if unspecifiedassets
— an absolute URL that matchesconfig.kit.paths.assets
, if specified, otherwise equal tobase
If a value for
config.kit.paths.assets
is specified, it will be replaced with'/_svelte_kit_assets'
duringsvelte-kit dev
orsvelte-kit preview
, since the assets don't yet live at their eventual URL.
$app/stores
import { getStores, navigating, page, session, updated } from '$app/stores';
Stores are contextual — they are added to the context of your root component. This means that session
and page
are unique to each request on the server, rather than shared between multiple requests handled by the same server simultaneously, which is what makes it safe to include user-specific data in session
.
Because of that, the stores are not free-floating objects: they must be accessed during component initialisation, like anything else that would be accessed with getContext
.
getStores
is a convenience function aroundgetContext
that returns{ navigating, page, session, updated }
. This needs to be called at the top-level or synchronously during component or page initialisation.
The stores themselves attach to the correct context at the point of subscription, which means you can import and use them directly in components without boilerplate. However, it still needs to be called synchronously on component or page initialisation when the $
-prefix isn't used. Use getStores
to safely .subscribe
asynchronously instead.
navigating
is a readable store. When navigating starts, its value is{ from, to }
, wherefrom
andto
are bothURL
instances. When navigating finishes, its value reverts tonull
.page
contains an object with the currenturl
,params
,stuff
,status
anderror
.session
is a writable store whose initial value is whatever was returned fromgetSession
. It can be written to, but this will not cause changes to persist on the server — this is something you must implement yourself.updated
is a readable store whose initial value is false. Ifversion.pollInterval
is a non-zero value, SvelteKit will poll for new versions of the app and update the store value totrue
when it detects one.updated.check()
will force an immediate check, regardless of polling.
$lib
This is a simple alias to src/lib
, or whatever directory is specified as [config.kit.files.lib
]. It allows you to access common components and utility modules without ../../../../
nonsense.
$service-worker
This module is only available to service workers.
import { build, files, timestamp } from '$service-worker';
build
is an array of URL strings representing the files generated by Vite, suitable for caching withcache.addAll(build)
files
is an array of URL strings representing the files in yourstatic
directory, or whatever directory is specified byconfig.kit.files.assets
. You can customize which files are included fromstatic
directory usingconfig.kit.serviceWorker.files
timestamp
is the result of callingDate.now()
at build time. It's useful for generating unique cache names inside your service worker, so that a later deployment of your app can invalidate old caches
@sveltejs/kit/hooks
This module provides a helper function to sequence multiple handle
calls.
import { sequence } from '@sveltejs/kit/hooks';
async function first({ event, resolve }) {
console.log('first pre-processing');
const result = await resolve(event);
console.log('first post-processing');
return result;
}
async function second({ event, resolve }) {
console.log('second pre-processing');
const result = await resolve(event);
console.log('second post-processing');
return result;
}
export const handle = sequence(first, second);
The example above would print:
first pre-processing second pre-processing second post-processing first post-processing
Service workers permalink
Service workers act as proxy servers that handle network requests inside your app. This makes it possible to make your app work offline, but even if you don't need offline support (or can't realistically implement it because of the type of app you're building), it's often worth using service workers to speed up navigation by precaching your built JS and CSS.
In SvelteKit, if you have a src/service-worker.js
file (or src/service-worker.ts
, or src/service-worker/index.js
, etc) it will be built with Vite and automatically registered. You can disable automatic registration if you need to register the service worker with your own logic (e.g. prompt user for update, configure periodic updates, use workbox
, etc).
You can change the location of your service worker and disable automatic registration in your project configuration.
Inside the service worker you have access to the $service-worker
module.
Because it needs to be bundled (since browsers don't yet support import
in this context), and depends on the client-side app's build manifest, service workers only work in the production build, not in development. To test it locally, use svelte-kit preview
.
Anchor options permalink
sveltekit:prefetch
SvelteKit uses code splitting to break your app into small chunks (one per route), ensuring fast startup times.
For dynamic routes, such as our src/routes/blog/[slug].svelte
example, that's not enough. In order to render the blog post, we need to fetch the data for it, and we can't do that until we know what slug
is. In the worst case, that could cause lag as the browser waits for the data to come back from the server.
We can mitigate that by prefetching the data. Adding a sveltekit:prefetch
attribute to a link...
<a sveltekit:prefetch href="blog/what-is-sveltekit">What is SvelteKit?</a>
...will cause SvelteKit to run the page's load
function as soon as the user hovers over the link (on a desktop) or touches it (on mobile), rather than waiting for the click
event to trigger navigation. Typically, this buys us an extra couple of hundred milliseconds, which is the difference between a user interface that feels laggy, and one that feels snappy.
Note that prefetching will not work if the router
setting is false
.
You can also programmatically invoke prefetch
from $app/navigation
.
sveltekit:noscroll
When navigating to internal links, SvelteKit mirrors the browser's default navigation behaviour: it will change the scroll position to 0,0 so that the user is at the very top left of the page (unless the link includes a #hash
, in which case it will scroll to the element with a matching ID).
In certain cases, you may wish to disable this behaviour. Adding a sveltekit:noscroll
attribute to a link...
<a href="path" sveltekit:noscroll>Path</a>
...will prevent scrolling after the link is clicked.
rel=external
By default, the SvelteKit runtime intercepts clicks on <a>
elements and bypasses the normal browser navigation for relative (same-origin) URLs that match one of your page routes. We sometimes need to tell SvelteKit that certain links need to be handled by normal browser navigation. Examples of this might be linking to another page on your domain that's not part of your SvelteKit app or linking to an endpoint.
Adding a rel=external
attribute to a link...
<a rel="external" href="path">Path</a>
...will trigger a browser navigation when the link is clicked.
Events permalink
SvelteKit emits CustomEvents on the window
object when certain things happen:
sveltekit:start
— fired once the app has hydratedsveltekit:navigation-start
— navigation has startedsveltekit:navigation-end
— navigation has ended
You probably won't need to use these, but they can be useful in the context of (for example) integration tests.
AMP permalink
An unfortunate reality of modern web development is that it is sometimes necessary to create an AMP version of your site. In SvelteKit this can be done by setting the amp
config option, which has the following effects:
- Client-side JavaScript, including the router, is disabled
- Styles are concatenated into
<style amp-custom>
, and the AMP boilerplate is injected - In development, requests are checked against the AMP validator so you get early warning of any errors
Adapters permalink
Before you can deploy your SvelteKit app, you need to adapt it for your deployment target. Adapters are small plugins that take the built app as input and generate output for deployment.
By default, projects are configured to use @sveltejs/adapter-auto
, which detects your production environment and selects the appropriate adapter where possible. If your platform isn't (yet) supported, you may need to install a custom adapter or write one.
See the adapter-auto README for information on adding support for new environments.
Supported environments
SvelteKit offers a number of officially-supported adapters.
The following platforms require no additional configuration:
Node.js
To create a simple Node server, install the @sveltejs/adapter-node@next
package and update your svelte.config.js
:
// svelte.config.js
-import adapter from '@sveltejs/adapter-auto';
+import adapter from '@sveltejs/adapter-node';
With this, svelte-kit build will generate a self-contained Node app inside the build
directory. You can pass options to adapters, such as customising the output directory:
// svelte.config.js
import adapter from '@sveltejs/adapter-node';
export default {
kit: {
- adapter: adapter()
+ adapter: adapter({ out: 'my-output-directory' })
}
};
Static sites
Most adapters will generate static HTML for any prerenderable pages of your site. In some cases, your entire app might be prerenderable, in which case you can use @sveltejs/adapter-static@next
to generate static HTML for all your pages. A fully static site can be hosted on a wide variety of platforms, including static hosts like GitHub Pages.
// svelte.config.js
-import adapter from '@sveltejs/adapter-auto';
+import adapter from '@sveltejs/adapter-static';
You can also use adapter-static
to generate single-page apps (SPAs) by specifying a fallback page.
Platform-specific context
Some adapters may have access to additional information about the request. For example, Cloudflare Workers can access an env
object containing KV namespaces etc. This can be passed to the RequestEvent
used in hooks and endpoints as the platform
property — consult each adapter's documentation to learn more.
Community adapters
Additional community-provided adapters exist for other platforms. After installing the relevant adapter with your package manager, update your svelte.config.js
:
// svelte.config.js
-import adapter from '@sveltejs/adapter-auto';
+import adapter from 'svelte-adapter-[x]';
Writing custom adapters
We recommend looking at the source for an adapter to a platform similar to yours and copying it as a starting point.
Adapters packages must implement the following API, which creates an Adapter
:
/** @param {AdapterSpecificOptions} options */
export default function (options) {
/** @type {import('@sveltejs/kit').Adapter} */
return {
name: 'adapter-package-name',
async adapt(builder) {
// adapter implementation
}
};
}
The types for Adapter
and its parameters are available in types/config.d.ts.
Within the adapt
method, there are a number of things that an adapter should do:
- Clear out the build directory
- Call
builder.prerender({ dest })
to prerender pages - Output code that:
- Imports
App
from${builder.getServerDirectory()}/app.js
- Instantiates the app with a manifest generated with
builder.generateManifest({ relativePath })
- Listens for requests from the platform, converts them to a standard Request if necessary, calls the
render
function to generate a Response and responds with it - expose any platform-specific information to SvelteKit via the
platform
option passed toapp.render
- Globally shims
fetch
to work on the target platform, if necessary. SvelteKit provides a@sveltejs/kit/install-fetch
helper for platforms that can usenode-fetch
- Imports
- Bundle the output to avoid needing to install dependencies on the target platform, if necessary
- Put the user's static files and the generated JS/CSS in the correct location for the target platform
Where possible, we recommend putting the adapter output under the build/
directory with any intermediate output placed under .svelte-kit/[adapter-name]
.
The adapter API may change before 1.0.
Page options permalink
By default, SvelteKit will render any component first on the server and send it to the client as HTML. It will then render the component again in the browser to make it interactive in a process called hydration. For this reason, you need to ensure that components can run in both places. SvelteKit will then initialise a router that takes over subsequent navigations.
You can control each of these on a per-app or per-page basis. Note that each of the per-page settings use context="module"
, and only apply to page components, not layout components.
If both are specified, per-page settings override per-app settings in case of conflicts.
router
SvelteKit includes a client-side router that intercepts navigations (from the user clicking on links, or interacting with the back/forward buttons) and updates the page contents, rather than letting the browser handle the navigation by reloading.
In certain circumstances you might need to disable client-side routing with the app-wide browser.router
config option or the page-level router
export:
<script context="module">
export const router = false;
</script>
Note that this will disable client-side routing for any navigation from this page, regardless of whether the router is already active.
hydrate
Ordinarily, SvelteKit hydrates your server-rendered HTML into an interactive page. Some pages don't require JavaScript at all — many blog posts and 'about' pages fall into this category. In these cases you can skip hydration when the app boots up with the app-wide browser.hydrate
config option or the page-level hydrate
export:
<script context="module">
export const hydrate = false;
</script>
If
hydrate
androuter
are bothfalse
, SvelteKit will not add any JavaScript to the page at all. If server-side rendering is disabled inhandle
,hydrate
must betrue
or no content will be rendered.
prerender
It's likely that at least some pages of your app can be represented as a simple HTML file generated at build time. These pages can be prerendered by your adapter.
If your entire app is suitable for prerendering, you could use adapter-static
, which will generate HTML files for every page, plus additional files that are requested by load
functions in those pages.
In many cases, you'll only want to prerender specific pages in your app. You'll need to annotate these pages:
<script context="module">
export const prerender = true;
</script>
The prerenderer will start at the root of your app and generate HTML for any prerenderable pages it finds. Each page is scanned for <a>
elements that point to other pages that are candidates for prerendering — because of this, you generally don't need to specify which pages should be accessed. If you do need to specify which pages should be accessed by the prerenderer, you can do so with the entries
option in the prerender configuration.
When not to prerender
The basic rule is this: for a page to be prerenderable, any two users hitting it directly must get the same content from the server.
Not all pages are suitable for prerendering. Any content that is prerendered will be seen by all users. You can of course fetch personalized data in
onMount
in a prerendered page, but this may result in a poorer user experience since it will involve blank initial content or loading indicators.
Note that you can still prerender pages that load data based on the page's parameters, like our src/routes/blog/[slug].svelte
example from earlier. The prerenderer will intercept requests made inside load
, so the data served from src/routes/blog/[slug].json.js
will also be captured.
Accessing url.searchParams
during prerendering is forbidden. If you need to use it, ensure you are only doing so in the browser (for example in onMount
).
Route conflicts
Because prerendering writes to the filesystem, it isn't possible to have two endpoints that would cause a directory and a file to have the same name. For example, src/routes/foo/index.js
and src/routes/foo/bar.js
would try to create foo
and foo/bar
, which is impossible.
For that reason among others, it's recommended that you always include a file extension — src/routes/foo/index.json.js
and src/routes/foo/bar.json.js
would result in foo.json
and foo/bar.json
files living harmoniously side-by-side.
For pages, we skirt around this problem by writing foo/index.html
instead of foo
.
Packaging permalink
You can use SvelteKit to build component libraries as well as apps.
When you're creating an app, the contents of src/routes
is the public-facing stuff; src/lib
contains your app's internal library.
A SvelteKit component library has the exact same structure as a SvelteKit app, except that src/lib
is the public-facing bit. src/routes
might be a documentation or demo site that accompanies the library, or it might just be a sandbox you use during development.
Running svelte-kit package
will take the contents of src/lib
and generate a package
directory (which can be configured) containing the following:
- All the files in
src/lib
, unless you configure custominclude
/exclude
options. Svelte components will be preprocessed, TypeScript files will be transpiled to JavaScript. - Type definitions (
d.ts
files) which are generated for Svelte, JavaScript and TypeScript files. You need to installtypescript >= 4.0.0
andsvelte2tsx >= 0.4.1
for this. Type definitions are placed next to their implementation, hand-writtend.ts
files are copied over as is. You can disable generation, but we strongly recommend against it. - A
package.json
copied from the project root with all fields but the"scripts"
field. The"dependencies"
field is included, which means you should add packages that you only need for your documentation or demo site to"devDependencies"
. A"type": "module"
and an"exports"
field will be added if it's not defined in the original file.
The "exports"
field contains the package's entry points. By default, all files in src/lib
will be treated as an entry point unless they start with (or live in a directory that starts with) an underscore, but you can configure this behaviour. If you have a src/lib/index.js
or src/lib/index.svelte
file, it will be treated as the package root.
For example, if you had a src/lib/Foo.svelte
component and a src/lib/index.js
module that re-exported it, a consumer of your library could do either of the following:
import { Foo } from 'your-library';
import Foo from 'your-library/Foo.svelte';
Publishing
To publish the generated package:
npm publish ./package
The ./package
above is referring to the directory name generated, change accordingly if you configure a custom package.dir
.
Caveats
This is a relatively experimental feature and is not yet fully implemented. All files except Svelte files (preprocessed) and TypeScript files (transpiled to JavaScript) are copied across as-is.
Command Line Interface permalink
SvelteKit includes a command line interface for building and running your app.
In the default project template svelte-kit dev
, svelte-kit build
and svelte-kit preview
are aliased as npm run dev
, npm run build
and npm run preview
respectively. You can also invoke the CLI with npx:
npx svelte-kit dev
svelte-kit dev
Starts a development server. It accepts the following options:
-p
/--port
— which port to start the server on-o
/--open
— open a browser tab once the server starts-h
/--host
— expose the server to the network.-H
/--https
— launch an HTTPS server using a self-signed certificate. Useful for testing HTTPS-only features on an external device
svelte-kit build
Builds a production version of your app, and runs your adapter if you have one specified in your config. It accepts the following option:
--verbose
— log more detail
After building the app, you can reference the documentation of your chosen adapter and hosting platform for specific instructions on how to serve your app.
svelte-kit preview
After you've built your app with svelte-kit build
, you can start the production version (irrespective of any adapter that has been applied) locally with svelte-kit preview
. This is intended for testing the production build locally, not for serving your app, for which you should always use an adapter.
Like svelte-kit dev
, it accepts the following options:
-p
/--port
-o
/--open
-h
/--host
-H
/--https
svelte-kit package
For package authors, see packaging.
Configuration permalink
Your project's configuration lives in a svelte.config.js
file. All values are optional. The complete list of options, with defaults, is shown here:
/** @type {import('@sveltejs/kit').Config} */
const config = {
// options passed to svelte.compile (https://svelte.dev/docs#compile-time-svelte-compile)
compilerOptions: null,
// an array of file extensions that should be treated as Svelte components
extensions: ['.svelte'],
kit: {
adapter: null,
amp: false,
appDir: '_app',
browser: {
hydrate: true,
router: true
},
csp: {
mode: 'auto',
directives: {
'default-src': undefined
// ...
}
},
files: {
assets: 'static',
hooks: 'src/hooks',
lib: 'src/lib',
routes: 'src/routes',
serviceWorker: 'src/service-worker',
template: 'src/app.html'
},
floc: false,
inlineStyleThreshold: 0,
methodOverride: {
parameter: '_method',
allowed: []
},
package: {
dir: 'package',
emitTypes: true,
// excludes all .d.ts and files starting with _ as the name
exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
files: () => true
},
paths: {
assets: '',
base: ''
},
prerender: {
concurrency: 1,
crawl: true,
createIndexFiles: true,
enabled: true,
entries: ['*'],
onError: 'fail'
},
routes: (filepath) => !/(?:(?:^_|\/_)|(?:^\.|\/\.)(?!well-known))/.test(filepath),
serviceWorker: {
register: true,
files: (filepath) => !/\.DS_STORE/.test(filepath)
},
trailingSlash: 'never',
version: {
name: Date.now().toString(),
pollInterval: 0
},
vite: () => ({})
},
// SvelteKit uses vite-plugin-svelte. Its options can be provided directly here.
// See the available options at https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/config.md
// options passed to svelte.preprocess (https://svelte.dev/docs#compile-time-svelte-preprocess)
preprocess: null
};
export default config;
adapter
Required when running svelte-kit build
and determines how the output is converted for different platforms. See Adapters.
amp
Enable AMP mode.
appDir
The directory relative to paths.assets
where the built JS and CSS (and imported assets) are served from. (The filenames therein contain content-based hashes, meaning they can be cached indefinitely). Must not start or end with /
.
browser
An object containing zero or more of the following boolean
values:
hydrate
— whether to hydrate the server-rendered HTML with a client-side app. (It's rare that you would set this tofalse
on an app-wide basis.)router
— enables or disables the client-side router app-wide.
csp
An object containing zero or more of the following values:
mode
— 'hash', 'nonce' or 'auto'directives
— an object of[directive]: value[]
pairs.
Content Security Policy configuration. CSP helps to protect your users against cross-site scripting (XSS) attacks, by limiting the places resources can be loaded from. For example, a configuration like this...
{
directives: {
'script-src': ['self']
}
}
...would prevent scripts loading from external sites. SvelteKit will augment the specified directives with nonces or hashes (depending on mode
) for any inline styles and scripts it generates.
When pages are prerendered, the CSP header is added via a <meta http-equiv>
tag (note that in this case, frame-ancestors
, report-uri
and sandbox
directives will be ignored).
When
mode
is'auto'
, SvelteKit will use nonces for dynamically rendered pages and hashes for prerendered pages. Using nonces with prerendered pages is insecure and therefore forbiddem.
files
An object containing zero or more of the following string
values:
assets
— a place to put static files that should have stable URLs and undergo no processing, such asfavicon.ico
ormanifest.json
hooks
— the location of your hooks module (see Hooks)lib
— your app's internal library, accessible throughout the codebase as$lib
routes
— the files that define the structure of your app (see Routing)serviceWorker
— the location of your service worker's entry point (see Service workers)template
— the location of the template for HTML responses
floc
Google's FLoC is a technology for targeted advertising that the Electronic Frontier Foundation has deemed harmful to user privacy. Browsers other than Chrome have declined to implement it.
In common with services like GitHub Pages, SvelteKit protects your users by automatically opting out of FLoC. It adds the following header to responses unless floc
is true
:
Permissions-Policy: interest-cohort=()
This only applies to server-rendered responses — headers for prerendered pages (e.g. created with adapter-static) are determined by the hosting platform.
inlineStyleThreshold
Inline CSS inside a <style>
block at the head of the HTML. This option is a number that specifies the maximum length of a CSS file to be inlined. All CSS files needed for the page and smaller than this value are merged and inlined in a <style>
block.
This results in fewer initial requests and can improve your First Contentful Paint score. However, it generates larger HTML output and reduces the effectiveness of browser caches. Use it advisedly.
methodOverride
See HTTP Method Overrides. An object containing zero or more of the following:
parameter
— query parameter name to use for passing the intended method valueallowed
- array of HTTP methods that can be used when overriding the original request method
package
Options related to creating a package.
dir
- output directoryemitTypes
- by default,svelte-kit package
will automatically generate types for your package in the form of.d.ts
files. While generating types is configurable, we believe it is best for the ecosystem quality to generate types, always. Please make sure you have a good reason when setting it tofalse
(for example when you want to provide handwritten type definitions instead)exports
- a function with the type of(filepath: string) => boolean
. Whentrue
, the filepath will be included in theexports
field of thepackage.json
. Any existing values in thepackage.json
source will be merged with values from the originalexports
field taking precedencefiles
- a function with the type of(filepath: string) => boolean
. Whentrue
, the file will be processed and copied over to the final output folder, specified indir
For advanced filepath
matching, you can use exports
and files
options in conjunction with a globbing library:
// svelte.config.js
import mm from 'micromatch';
export default {
kit: {
package: {
exports: (filepath) => {
if (filepath.endsWith('.d.ts')) return false;
return mm.isMatch(filepath, ['!**/_*', '!**/internal/**']);
},
files: mm.matcher('!**/build.*')
}
}
};
paths
An object containing zero or more of the following string
values:
assets
— an absolute path that your app's files are served from. This is useful if your files are served from a storage bucket of some kindbase
— a root-relative path that must start, but not end with/
(e.g./base-path
). This specifies where your app is served from and allows the app to live on a non-root path
prerender
See Prerendering. An object containing zero or more of the following:
concurrency
— how many pages can be prerendered simultaneously. JS is single-threaded, but in cases where prerendering performance is network-bound (for example loading content from a remote CMS) this can speed things up by processing other tasks while waiting on the network responsecrawl
— determines whether SvelteKit should find pages to prerender by following links from the seed page(s)createIndexFiles
- if set tofalse
, will renderabout.html
instead ofabout/index.html
enabled
— set tofalse
to disable prerendering altogetherentries
— an array of pages to prerender, or start crawling from (ifcrawl: true
). The*
string includes all non-dynamic routes (i.e. pages with no[parameters]
)onError
'fail'
— (default) fails the build when a routing error is encountered when following a link'continue'
— allows the build to continue, despite routing errorsfunction
— custom error handler allowing you to log,throw
and fail the build, or take other action of your choosing based on the details of the crawlimport adapter from '@sveltejs/adapter-static'; /** @type {import('@sveltejs/kit').PrerenderErrorHandler} */ const handleError = ({ status, path, referrer, referenceType }) => { if (path.startsWith('/blog')) throw new Error('Missing a blog page!'); console.warn(`${status} ${path}${referrer ? ` (${referenceType} from ${referrer})` : ''}`); }; export default { kit: { adapter: adapter(), prerender: { onError: handleError } } };
routes
A (filepath: string) => boolean
function that determines which files create routes and which are treated as private modules.
serviceWorker
An object containing zero or more of the following values:
register
- if set tofalse
, will disable automatic service worker registrationfiles
- a function with the type of(filepath: string) => boolean
. Whentrue
, the given file will be available in$service-worker.files
, otherwise it will be excluded.
trailingSlash
Whether to remove, append, or ignore trailing slashes when resolving URLs to routes.
"never"
— redirect/x/
to/x
"always"
— redirect/x
to/x/
"ignore"
— don't automatically add or remove trailing slashes./x
and/x/
will be treated equivalently
Ignoring trailing slashes is not recommended — the semantics of relative paths differ between the two cases (
./y
from/x
is/y
, but from/x/
is/x/y
), and/x
and/x/
are treated as separate URLs which is harmful to SEO. If you use this option, ensure that you implement logic for conditionally adding or removing trailing slashes fromrequest.path
inside yourhandle
function.
version
An object containing zero or more of the following values:
name
- current app version stringpollInterval
- interval in milliseconds to poll for version changes
Client-side navigation can be buggy if you deploy a new version of your app while people are using it. If the code for the new page is already loaded, it may have stale content; if it isn't, the app's route manifest may point to a JavaScript file that no longer exists. SvelteKit solves this problem by falling back to traditional full-page navigation if it detects that a new version has been deployed, using the name
specified here (which defaults to a timestamp of the build).
If you set pollInterval
to a non-zero value, SvelteKit will poll for new versions in the background and set the value of the updated
store to true
when it detects one.
vite
A Vite config object, or a function that returns one. You can pass Vite and Rollup plugins via the plugins
option to customize your build in advanced ways such as supporting image optimization, Tauri, WASM, Workbox, and more. SvelteKit will prevent you from setting certain build-related options since it depends on certain configuration values.
TypeScript permalink
All APIs in SvelteKit are fully typed. Additionally, it's possible to tell SvelteKit how to type objects inside your app by declaring the App
namespace. By default, a new project will have a file called src/app.d.ts
containing the following:
/// <reference types="@sveltejs/kit" />
declare namespace App {
interface Locals {}
interface Platform {}
interface Session {}
interface Stuff {}
}
By populating these interfaces, you will gain type safety when using event.locals
, event.platform
, session
and stuff
:
App.Locals
The interface that defines event.locals
, which can be accessed in hooks (handle
, handleError
and getSession
) and endpoints.
App.Platform
If your adapter provides platform-specific context via event.platform
, you can specify it here.
App.Session
The interface that defines session
, both as an argument to load
functions and the value of the session store.
App.Stuff
The interface that defines stuff
, as input or output to load
or as the value of the stuff
property of the page store.
Additional Resources permalink
FAQs
Please see the SvelteKit FAQ for solutions to common issues and helpful tips and tricks.
The Svelte FAQ and vite-plugin-svelte
FAQ may also be helpful for questions deriving from those libraries.
Examples
We've written and published a few different SvelteKit sites as examples:
sveltejs/realworld
contains an example blog site- The
sites/kit.svelte.dev
directory contains the code for this site sveltejs/sites
contains the code for svelte.dev and for a HackerNews clone
SvelteKit users have also published plenty of examples on GitHub, under the #sveltekit and #sveltekit-template topics, as well as on the Svelte Society site. Note that these have not been vetted by the maintainers and may not be up to date.
Integrations
svelte-preprocess
automatically transforms the code in your Svelte templates to provide support for TypeScript, PostCSS, scss/sass, Less, and many other technologies (except CoffeeScript which is not supported by SvelteKit). The first step of setting it up is to add svelte-preprocess
to your svelte.config.js
. It is provided by the template if you're using TypeScript whereas JavaScript users will need to add it. After that, you will often only need to install the corresponding library such as npm install -D sass
or npm install -D less
. See the svelte-preprocess
docs for more details.
Svelte Adders allow you to setup many different complex integrations like Tailwind, PostCSS, Firebase, GraphQL, mdsvex, and more with a single command. Please see sveltesociety.dev for a full listing of templates, components, and tools available for use with Svelte and SvelteKit.
The SvelteKit FAQ also has a section on integrations, which may be helpful if you run into any issues.
Support
You can ask for help on Discord and StackOverflow. Please first search for information related to your issue in the FAQ, Google or another search engine, issue tracker, and Discord chat history in order to be respectful of others' time. There are many more people asking questions than answering them, so this will help in allowing the community to grow in a scalable fashion.
Appendix permalink
The core of SvelteKit provides a highly configurable rendering engine. This section describes some of the terms used when discussing rendering. A reference for setting these options is provided in the documentation above.
SSR
Server-side rendering (SSR) is the generation of the page contents on the server. SSR is generally preferred for SEO. While some search engines can index content that is dynamically generated on the client-side it may take longer even in these cases. It also tends to improve perceived performance and makes your app accessible to users if JavaScript fails or is disabled (which happens more often than you probably think).
CSR and SPA
Client-side rendering (CSR) is the generation of the page contents in the web browser using JavaScript. A single-page app (SPA) is an application in which all requests to the server load a single HTML file which then does client-side rendering of the requested contents based on the requested URL. All navigation is handled on the client-side in a process called client-side routing with per-page contents being updated and common layout elements remaining largely unchanged. SPAs do not provide SSR, which has the shortcoming described above. However, some applications are not greatly impacted by these shortcomings such as a complex business application behind a login where SEO would not be important and it is known that users will be accessing the application from a consistent computing environment.
Prerendering
Prerendering means computing the contents of a page at build time and saving the HTML for display. This approach has the same benefits as traditional server-rendered pages, but avoids recomputing the page for each visitor and so scales nearly for free as the number of visitors increases. The tradeoff is that the build process is more expensive and prerendered content can only be updated by building and deploying a new version of the application.
Not all pages can be prerendered. The basic rule is this: for content to be prerenderable, any two users hitting it directly must get the same content from the server. Note that you can still prerender content that is loaded based on the page's parameters as long as all users will be seeing the same prerendered content.
Pre-rendered pages are not limited to static content. You can build personalized pages if user-specific data is fetched and rendered client-side. This is subject to the caveat that you will experience the downsides of not doing SSR for that content as discussed above.
SSG
Static Site Generation (SSG) is a term that refers to a site where every page is prerendered. This is what SvelteKit's adapter-static
does. SvelteKit was not built to do only static site generation like some tools and so may not scale as well to efficiently render a very large number of pages as tools built specifically for that purpose. However, in contrast to most purpose-built SSGs, SvelteKit does nicely allow for mixing and matching different rendering types on different pages. One benefit of fully prerendering a site is that you do not need to maintain or pay for servers to perform SSR. Once generated, the site can be served from CDNs, leading to great "time to first byte" performance. This delivery model is often referred to as JAMstack.
Hydration
Svelte components store some state and update the DOM when the state is updated. When fetching data during SSR, by default SvelteKit will store this data and transmit it to the client along with the server-rendered HTML. The components can then be initialized on the client with that data without having to call the same API endpoints again. Svelte will then check that the DOM is in the expected state and attach event listeners in a process called hydration. Once the components are fully hydrated, they can react to changes to their properties just like any newly created Svelte component.
Routing
By default, when you navigate to a new page (by clicking on a link or using the browser's forward or back buttons), SvelteKit will intercept the attempted navigation and handle it instead of allowing the browser to send a request to the server for the destination page. SvelteKit will then update the displayed contents on the client by rendering the component for the new page, which in turn can make calls to the necessary API endpoints. This process of updating the page on the client in response to attempted navigation is called client-side routing.