Getting started
Core concepts
Build and deploy
Advanced
Best practices
Appendix
Reference
- @sveltejs/kit
- @sveltejs/kit/hooks
- @sveltejs/kit/node/polyfills
- @sveltejs/kit/node
- @sveltejs/kit/vite
- $app/environment
- $app/forms
- $app/navigation
- $app/paths
- $app/server
- $app/state
- $app/stores
- $env/dynamic/private
- $env/dynamic/public
- $env/static/private
- $env/static/public
- $lib
- $service-worker
- Configuration
- Command Line Interface
- Types
Hooks
‘Hooks’ are app-wide functions you declare that SvelteKit will call in response to specific events, giving you fine-grained control over the framework’s behaviour.
There are three hooks files, all optional:
src/hooks.server.js
— your app’s server hookssrc/hooks.client.js
— your app’s client hookssrc/hooks.js
— your app’s hooks that run on both the client and server
Code in these modules will run when the application starts up, making them useful for initializing database clients and so on.
You can configure the location of these files with
config.kit.files.hooks
.
Server hooks
The following hooks can be added tosrc/hooks.server.js
:
handle
This function runs every time the SvelteKit server receives arequest — whether that happens while the app is running, or duringprerendering — and determines theresponse. It receives anevent
object representing the request and a function calledresolve
, which renders the route and generates aResponse
. This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
/**@type{import('@sveltejs/kit').Handle}*/exportasyncfunctionfunctionhandle({ event,resolve }:{event:any;resolve:any;}):Promise<any>
@type{import('@sveltejs/kit').Handle}handle({event:any
event,resolve:any
resolve}) {if(event:any
event.url.pathname.startsWith('/custom')) {returnnewvarResponse:new(body?:BodyInit|null,init?:ResponseInit)=>Response
This Fetch API interface represents the response to a request.
Response('custom response');}constconstresponse:any
response=awaitresolve:any
resolve(event:any
event);returnconstresponse:any
response;}
importtype{typeHandle=(input:{event:RequestEvent;resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>;})=>MaybePromise<...>
Thehandle
hook runs every time the SvelteKit server receives arequest anddetermines theresponse.It receives anevent
object representing the request and a function calledresolve
, which renders the route and generates aResponse
.This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle}from'@sveltejs/kit';exportconstconsthandle:Handle
handle:typeHandle=(input:{event:RequestEvent;resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>;})=>MaybePromise<...>
Thehandle
hook runs every time the SvelteKit server receives arequest anddetermines theresponse.It receives anevent
object representing the request and a function calledresolve
, which renders the route and generates aResponse
.This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle=async({event:RequestEvent<Partial<Record<string,string>>,string|null>
event,resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>
resolve})=>{if(event:RequestEvent<Partial<Record<string,string>>,string|null>
event.RequestEvent<Partial<Record<string,string>>,string|null>.url:URL
The requested URL.
url.URL.pathname: string
pathname.String.startsWith(searchString: string,position?:number): boolean
Returns true if the sequence of elements of searchString converted to a String is thesame as the corresponding elements of this object (converted to a String) starting atposition. Otherwise returns false.
startsWith('/custom')) {returnnewvarResponse:new(body?:BodyInit|null,init?:ResponseInit)=>Response
This Fetch API interface represents the response to a request.
Response('custom response');}constconstresponse:Response
response=awaitresolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>
resolve(event:RequestEvent<Partial<Record<string,string>>,string|null>
event);returnconstresponse:Response
response;};
Requests for static assets — which includes pages that were already prerendered — arenot handled by SvelteKit.
If unimplemented, defaults to({ event, resolve }) => resolve(event)
.
During prerendering, SvelteKit crawls your pages for links and renders each route it finds. Rendering the route invokes thehandle
function (and all other route dependencies, likeload
). If you need to exclude some code from running during this phase, check that the app is notbuilding
beforehand.
locals
To add custom data to the request, which is passed to handlers in+server.js
and serverload
functions, populate theevent.locals
object, as shown below.
/**@type{import('@sveltejs/kit').Handle}*/exportasyncfunctionfunctionhandle(input:{event:RequestEvent;resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>;}):MaybePromise<...>
@type{import('@sveltejs/kit').Handle}handle({event:RequestEvent<Partial<Record<string,string>>,string|null>
event,resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>
resolve}) {event:RequestEvent<Partial<Record<string,string>>,string|null>
event.RequestEvent<Partial<Record<string,string>>,string|null>.locals:App.Locals
Contains custom data that was added to the request within theserver handle hook
.
locals.App.Locals.user: User
user=awaitconstgetUserInformation:(cookie:string|void)=>Promise<User>
getUserInformation(event:RequestEvent<Partial<Record<string,string>>,string|null>
event.RequestEvent<Partial<Record<string,string>>,string|null>.cookies: Cookies
Get or set cookies related to the current request
cookies.Cookies.get: (name:string,opts?:CookieParseOptions)=>string|undefined
Gets a cookie that was previously set withcookies.set
, or from the request headers.
@paramname the name of the cookie@paramopts the options, passed directly tocookie.parse
. See documentationhereget('sessionid'));constconstresponse:Response
response=awaitresolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>
resolve(event:RequestEvent<Partial<Record<string,string>>,string|null>
event);// Note that modifying response headers isn't always safe.// Response objects can have immutable headers// (e.g. Response.redirect() returned from an endpoint).// Modifying immutable headers throws a TypeError.// In that case, clone the response or avoid creating a// response object with immutable headers.constresponse:Response
response.Response.headers: Headers
headers.Headers.set(name: string,value: string):void
set('x-custom-header','potato');returnconstresponse:Response
response;}
importtype{typeHandle=(input:{event:RequestEvent;resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>;})=>MaybePromise<...>
Thehandle
hook runs every time the SvelteKit server receives arequest anddetermines theresponse.It receives anevent
object representing the request and a function calledresolve
, which renders the route and generates aResponse
.This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle}from'@sveltejs/kit';exportconstconsthandle:Handle
handle:typeHandle=(input:{event:RequestEvent;resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>;})=>MaybePromise<...>
Thehandle
hook runs every time the SvelteKit server receives arequest anddetermines theresponse.It receives anevent
object representing the request and a function calledresolve
, which renders the route and generates aResponse
.This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle=async({event:RequestEvent<Partial<Record<string,string>>,string|null>
event,resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>
resolve})=>{event:RequestEvent<Partial<Record<string,string>>,string|null>
event.RequestEvent<Partial<Record<string,string>>,string|null>.locals:App.Locals
Contains custom data that was added to the request within theserver handle hook
.
locals.App.Locals.user: User
user=awaitconstgetUserInformation:(cookie:string|void)=>Promise<User>
getUserInformation(event:RequestEvent<Partial<Record<string,string>>,string|null>
event.RequestEvent<Partial<Record<string,string>>,string|null>.cookies: Cookies
Get or set cookies related to the current request
cookies.Cookies.get: (name:string,opts?:CookieParseOptions)=>string|undefined
Gets a cookie that was previously set withcookies.set
, or from the request headers.
@paramname the name of the cookie@paramopts the options, passed directly tocookie.parse
. See documentationhereget('sessionid'));constconstresponse:Response
response=awaitresolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>
resolve(event:RequestEvent<Partial<Record<string,string>>,string|null>
event);// Note that modifying response headers isn't always safe.// Response objects can have immutable headers// (e.g. Response.redirect() returned from an endpoint).// Modifying immutable headers throws a TypeError.// In that case, clone the response or avoid creating a// response object with immutable headers.constresponse:Response
response.Response.headers: Headers
headers.Headers.set(name: string,value: string):void
set('x-custom-header','potato');returnconstresponse:Response
response;};
You can define multiplehandle
functions and execute them withthesequence
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:
transformPageChunk(opts: { html: string, done: boolean }): MaybePromise<string | undefined>
— applies custom transforms to HTML. Ifdone
is true, it’s the final chunk. Chunks are not guaranteed to be well-formed HTML (they could include an element’s opening tag but not its closing tag, for example) but they will always be split at sensible boundaries such as%sveltekit.head%
or layout/page components.filterSerializedResponseHeaders(name: string, value: string): boolean
— determines which headers should be included in serialized responses when aload
function loads a resource withfetch
. By default, none will be included.preload(input: { type: 'js' | 'css' | 'font' | 'asset', path: string }): boolean
— determines what files should be added to the<head>
tag to preload it. The method is called with each file that was found at build time while constructing the code chunks — so if you for example haveimport './styles.css
in your+page.svelte
,preload
will be called with the resolved path to that CSS file when visiting that page. Note that in dev modepreload
isnot called, since it depends on analysis that happens at build time. Preloading can improve performance by downloading assets sooner, but it can also hurt if too much is downloaded unnecessarily. By default,js
andcss
files will be preloaded.asset
files are not preloaded at all currently, but we may add this later after evaluating feedback.
/**@type{import('@sveltejs/kit').Handle}*/exportasyncfunctionfunctionhandle({ event,resolve }:{event:any;resolve:any;}):Promise<any>
@type{import('@sveltejs/kit').Handle}handle({event:any
event,resolve:any
resolve}) {constconstresponse:any
response=awaitresolve:any
resolve(event:any
event,{transformPageChunk:({ html }: {html:any;})=>any
transformPageChunk:({html:any
html})=>html:any
html.replace('old','new'),filterSerializedResponseHeaders:(name:any)=>any
filterSerializedResponseHeaders:(name:any
name)=>name:any
name.startsWith('x-'),preload:({ type,path }: {type:any;path: any;})=>any
preload:({type:any
type,path:any
path})=>type:any
type==='js'||path:any
path.includes('/important/')});returnconstresponse:any
response;}
importtype{typeHandle=(input:{event:RequestEvent;resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>;})=>MaybePromise<...>
Thehandle
hook runs every time the SvelteKit server receives arequest anddetermines theresponse.It receives anevent
object representing the request and a function calledresolve
, which renders the route and generates aResponse
.This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle}from'@sveltejs/kit';exportconstconsthandle:Handle
handle:typeHandle=(input:{event:RequestEvent;resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>;})=>MaybePromise<...>
Thehandle
hook runs every time the SvelteKit server receives arequest anddetermines theresponse.It receives anevent
object representing the request and a function calledresolve
, which renders the route and generates aResponse
.This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle=async({event:RequestEvent<Partial<Record<string,string>>,string|null>
event,resolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>
resolve})=>{constconstresponse:Response
response=awaitresolve:(event:RequestEvent,opts?:ResolveOptions)=>MaybePromise<Response>
resolve(event:RequestEvent<Partial<Record<string,string>>,string|null>
event,{ResolveOptions.transformPageChunk?:((input:{html:string;done:boolean;})=>MaybePromise<string|undefined>)|undefined
Applies custom transforms to HTML. Ifdone
is true, it’s the final chunk. Chunks are not guaranteed to be well-formed HTML(they could include an element’s opening tag but not its closing tag, for example)but they will always be split at sensible boundaries such as%sveltekit.head%
or layout/page components.
@paraminput the html chunk and the info if this is the last chunktransformPageChunk:({html:string
html})=>html:string
html.String.replace(searchValue: string|RegExp,replaceValue: string):string(+3overloads)
Replaces text in a string, using a regular expression or search string.
@paramsearchValue A string or regular expression to search for.@paramreplaceValue A string containing the text to replace. When the {@linkcode searchValue} is aRegExp
, all matches are replaced if theg
flag is set (or only those matches at the beginning, if they
flag is also present). Otherwise, only the first match of {@linkcode searchValue} is replaced.replace('old','new'),ResolveOptions.filterSerializedResponseHeaders?:((name:string,value:string)=>boolean)|undefined
Determines which headers should be included in serialized responses when aload
function loads a resource withfetch
.By default, none will be included.
@paramname header name@paramvalue header valuefilterSerializedResponseHeaders:(name:string
name)=>name:string
name.String.startsWith(searchString: string,position?:number): boolean
Returns true if the sequence of elements of searchString converted to a String is thesame as the corresponding elements of this object (converted to a String) starting atposition. Otherwise returns false.
startsWith('x-'),ResolveOptions.preload?:((input:{type:"font"|"css"|"js"|"asset";path:string;})=>boolean)|undefined
Determines what should be added to the<head>
tag to preload it.By default,js
andcss
files will be preloaded.
@paraminput the type of the file and its pathpreload:({type:"font"|"css"|"js"|"asset"
type,path:string
path})=>type:"font"|"css"|"js"|"asset"
type==='js'||path:string
path.String.includes(searchString: string,position?:number): boolean
Returns true if searchString appears as a substring of the result of converting thisobject to a String, at one or more positions that aregreater than or equal to position; otherwise, returns false.
@paramsearchString search string@paramposition If position is undefined, 0 is assumed, so as to search all of the String.includes('/important/')});returnconstresponse:Response
response;};
Note thatresolve(...)
will never throw an error, it will always return aPromise<Response>
with the appropriate status code. If an error is thrown elsewhere duringhandle
, it is treated as fatal, and SvelteKit will respond with a JSON representation of the error or a fallback error page — which can be customised viasrc/error.html
— depending on theAccept
header. You can read more about error handlinghere.
handleFetch
This function allows you to modify (or replace) afetch
request that happens inside aload
oraction
function that runs on the server (or during pre-rendering).
For example, yourload
function might make a request to a public URL likehttps://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).
/**@type{import('@sveltejs/kit').HandleFetch}*/exportasyncfunctionfunctionhandleFetch({ request,fetch }:{request:any;fetch:any;}):Promise<any>
@type{import('@sveltejs/kit').HandleFetch}handleFetch({request:any
request,fetch:any
fetch}) {if(request:any
request.url.startsWith('https://api.yourapp.com/')) {// clone the original request, but change the URLrequest:any
request=newvarRequest:new(input:RequestInfo|URL,init?:RequestInit)=>Request
This Fetch API interface represents a resource request.
Request(request:any
request.url.replace('https://api.yourapp.com/','http://localhost:9999/'),request:any
request);}returnfetch:any
fetch(request:any
request);}
importtype{typeHandleFetch=(input:{event:RequestEvent;request:Request;fetch:typeoffetch;})=>MaybePromise<Response>
ThehandleFetch
hook allows you to modify (or replace) afetch
request that happens inside aload
function that runs on the server (or during pre-rendering)
HandleFetch}from'@sveltejs/kit';exportconstconsthandleFetch:HandleFetch
handleFetch:typeHandleFetch=(input:{event:RequestEvent;request:Request;fetch:typeoffetch;})=>MaybePromise<Response>
ThehandleFetch
hook allows you to modify (or replace) afetch
request that happens inside aload
function that runs on the server (or during pre-rendering)
HandleFetch=async({request:Request
request,fetch:{(input:RequestInfo|URL,init?:RequestInit):Promise<Response>;(input:string|URL|globalThis.Request,init?:RequestInit):Promise<Response>;}
fetch})=>{if(request:Request
request.Request.url: string
Returns the URL of request as a string.
url.String.startsWith(searchString: string,position?:number): boolean
Returns true if the sequence of elements of searchString converted to a String is thesame as the corresponding elements of this object (converted to a String) starting atposition. Otherwise returns false.
startsWith('https://api.yourapp.com/')) {// clone the original request, but change the URLrequest:Request
request=newvarRequest:new(input:RequestInfo|URL,init?:RequestInit)=>Request
This Fetch API interface represents a resource request.
Request(request:Request
request.Request.url: string
Returns the URL of request as a string.
url.String.replace(searchValue: string|RegExp,replaceValue: string):string(+3overloads)
Replaces text in a string, using a regular expression or search string.
@paramsearchValue A string or regular expression to search for.@paramreplaceValue A string containing the text to replace. When the {@linkcode searchValue} is aRegExp
, all matches are replaced if theg
flag is set (or only those matches at the beginning, if they
flag is also present). Otherwise, only the first match of {@linkcode searchValue} is replaced.replace('https://api.yourapp.com/','http://localhost:9999/'),request:Request
request);}returnfetch:(input:string|URL|globalThis.Request,init?:RequestInit)=>Promise<Response> (+1overload)
fetch(request:Request
request);};
Credentials
For same-origin requests, SvelteKit’sfetch
implementation will forwardcookie
andauthorization
headers unless thecredentials
option is set to"omit"
.
For cross-origin requests,cookie
will be included if the request URL belongs to a subdomain of the app — for example if your app is onmy-domain.com
, and your API is onapi.my-domain.com
, cookies will be included in the request.
If your app and your API are on sibling subdomains —www.my-domain.com
andapi.my-domain.com
for example — then a cookie belonging to a common parent domain likemy-domain.com
willnot be included, because SvelteKit has no way to know which domain the cookie belongs to. In these cases you will need to manually include the cookie usinghandleFetch
:
/**@type{import('@sveltejs/kit').HandleFetch}*/exportasyncfunctionfunctionhandleFetch({ event,request,fetch }:{event:any;request:any;fetch:any;}):Promise<any>
@type{import('@sveltejs/kit').HandleFetch}handleFetch({event:any
event,request:any
request,fetch:any
fetch}) {if(request:any
request.url.startsWith('https://api.my-domain.com/')) {request:any
request.headers.set('cookie',event:any
event.request.headers.get('cookie'));}returnfetch:any
fetch(request:any
request);}
importtype{typeHandleFetch=(input:{event:RequestEvent;request:Request;fetch:typeoffetch;})=>MaybePromise<Response>
ThehandleFetch
hook allows you to modify (or replace) afetch
request that happens inside aload
function that runs on the server (or during pre-rendering)
HandleFetch}from'@sveltejs/kit';exportconstconsthandleFetch:HandleFetch
handleFetch:typeHandleFetch=(input:{event:RequestEvent;request:Request;fetch:typeoffetch;})=>MaybePromise<Response>
ThehandleFetch
hook allows you to modify (or replace) afetch
request that happens inside aload
function that runs on the server (or during pre-rendering)
HandleFetch=async({event:RequestEvent<Partial<Record<string,string>>,string|null>
event,request:Request
request,fetch:{(input:RequestInfo|URL,init?:RequestInit):Promise<Response>;(input:string|URL|globalThis.Request,init?:RequestInit):Promise<Response>;}
fetch})=>{if(request:Request
request.Request.url: string
Returns the URL of request as a string.
url.String.startsWith(searchString: string,position?:number): boolean
Returns true if the sequence of elements of searchString converted to a String is thesame as the corresponding elements of this object (converted to a String) starting atposition. Otherwise returns false.
startsWith('https://api.my-domain.com/')) {request:Request
request.Request.headers: Headers
Returns a Headers object consisting of the headers associated with request. Note that headers added in the network layer by the user agent will not be accounted for in this object, e.g., the “Host” header.
headers.Headers.set(name: string,value: string):void
set('cookie',event:RequestEvent<Partial<Record<string,string>>,string|null>
event.RequestEvent<Partial<Record<string,string>>,string|null>.request: Request
The original request object.
request.Request.headers: Headers
Returns a Headers object consisting of the headers associated with request. Note that headers added in the network layer by the user agent will not be accounted for in this object, e.g., the “Host” header.
headers.Headers.get(name: string): string|null
get('cookie'));}returnfetch:(input:string|URL|globalThis.Request,init?:RequestInit)=>Promise<Response> (+1overload)
fetch(request:Request
request);};
Shared hooks
The following can be added tosrc/hooks.server.js
andsrc/hooks.client.js
:
handleError
If anunexpected error is thrown during loading or rendering, this function will be called with theerror
,event
,status
code andmessage
. This allows for two things:
- you can log the error
- you can generate a custom representation of the error that is safe to show to users, omitting sensitive details like messages and stack traces. The returned value, which defaults to
{ message }
, becomes the value of$page.error
.
For errors thrown from your code (or library code called by your code) the status will be 500 and the message will be “Internal Error”. Whileerror.message
may contain sensitive information that should not be exposed to users,message
is safe (albeit meaningless to the average user).
To add more information to the$page.error
object in a type-safe way, you can customize the expected shape by declaring anApp.Error
interface (which must includemessage: string
, to guarantee sensible fallback behavior). This allows you to — for example — append a tracking ID for users to quote in correspondence with your technical support staff:
declareglobal{namespaceApp{interfaceinterfaceApp.Error
Defines the common shape of expected and unexpected errors. Expected errors are thrown using theerror
function. Unexpected errors are handled by thehandleError
hooks which should return this shape.
Error{App.Error.message: string
message:string;App.Error.errorId: string
errorId:string;}}}export{};
import*asmodule"@sentry/sveltekit"
Sentryfrom'@sentry/sveltekit';module"@sentry/sveltekit"
Sentry.constinit:(opts:any)=>void
init({/*...*/})/**@type{import('@sveltejs/kit').HandleServerError}*/exportasyncfunctionfunctionhandleError(input:{error:unknown;event:RequestEvent;status:number;message:string;}):MaybePromise<void|App.Error>
@type{import('@sveltejs/kit').HandleServerError}handleError({error:unknown
error,event:RequestEvent<Partial<Record<string,string>>,string|null>
event,status:number
status,message:string
message}) {constconsterrorId:`${string}-${string}-${string}-${string}-${string}`
errorId=varcrypto:Crypto
crypto.Crypto.randomUUID():`${string}-${string}-${string}-${string}-${string}`
Available only in secure contexts.
randomUUID();// example integration with https://sentry.io/module"@sentry/sveltekit"
Sentry.constcaptureException:(error:any,opts:any)=>void
captureException(error:unknown
error,{extra:{event:RequestEvent<Partial<Record<string,string>>,string|null>;errorId:`${string}-${string}-${string}-${string}-${string}`;status:number;}
extra:{event:RequestEvent<Partial<Record<string,string>>,string|null>
event,errorId:`${string}-${string}-${string}-${string}-${string}`
errorId,status:number
status}});return{App.Error.message: string
message:'Whoops!',errorId};}
import*asmodule"@sentry/sveltekit"
Sentryfrom'@sentry/sveltekit';importtype{typeHandleServerError=(input:{error:unknown;event:RequestEvent;status:number;message:string;})=>MaybePromise<void|App.Error>
The server-sidehandleError
hook runs when an unexpected error is thrown while responding to a request.
If an unexpected error is thrown during loading or rendering, this function will be called with the error and the event.Make sure that this functionnever throws an error.
HandleServerError}from'@sveltejs/kit';module"@sentry/sveltekit"
Sentry.constinit:(opts:any)=>void
init({/*...*/})exportconstconsthandleError:HandleServerError
handleError:typeHandleServerError=(input:{error:unknown;event:RequestEvent;status:number;message:string;})=>MaybePromise<void|App.Error>
The server-sidehandleError
hook runs when an unexpected error is thrown while responding to a request.
If an unexpected error is thrown during loading or rendering, this function will be called with the error and the event.Make sure that this functionnever throws an error.
HandleServerError=async({error:unknown
error,event:RequestEvent<Partial<Record<string,string>>,string|null>
event,status:number
status,message:string
message})=>{constconsterrorId:`${string}-${string}-${string}-${string}-${string}`
errorId=varcrypto:Crypto
crypto.Crypto.randomUUID():`${string}-${string}-${string}-${string}-${string}`
Available only in secure contexts.
randomUUID();// example integration with https://sentry.io/module"@sentry/sveltekit"
Sentry.constcaptureException:(error:any,opts:any)=>void
captureException(error:unknown
error,{extra:{event:RequestEvent<Partial<Record<string,string>>,string|null>;errorId:`${string}-${string}-${string}-${string}-${string}`;status:number;}
extra:{event:RequestEvent<Partial<Record<string,string>>,string|null>
event,errorId:`${string}-${string}-${string}-${string}-${string}`
errorId,status:number
status}});return{App.Error.message: string
message:'Whoops!',errorId:`${string}-${string}-${string}-${string}-${string}`
errorId};};
import*asmodule"@sentry/sveltekit"
Sentryfrom'@sentry/sveltekit';module"@sentry/sveltekit"
Sentry.constinit:(opts:any)=>void
init({/*...*/})/**@type{import('@sveltejs/kit').HandleClientError}*/exportasyncfunctionfunctionhandleError(input:{error:unknown;event:NavigationEvent;status:number;message:string;}):MaybePromise<void|App.Error>
@type{import('@sveltejs/kit').HandleClientError}handleError({error:unknown
error,event:NavigationEvent<Partial<Record<string,string>>,string|null>
event,status:number
status,message:string
message}) {constconsterrorId:`${string}-${string}-${string}-${string}-${string}`
errorId=varcrypto:Crypto
crypto.Crypto.randomUUID():`${string}-${string}-${string}-${string}-${string}`
Available only in secure contexts.
randomUUID();// example integration with https://sentry.io/module"@sentry/sveltekit"
Sentry.constcaptureException:(error:any,opts:any)=>void
captureException(error:unknown
error,{extra:{event:NavigationEvent<Partial<Record<string,string>>,string|null>;errorId:`${string}-${string}-${string}-${string}-${string}`;status:number;}
extra:{event:NavigationEvent<Partial<Record<string,string>>,string|null>
event,errorId:`${string}-${string}-${string}-${string}-${string}`
errorId,status:number
status}});return{App.Error.message: string
message:'Whoops!',errorId};}
import*asmodule"@sentry/sveltekit"
Sentryfrom'@sentry/sveltekit';importtype{typeHandleClientError=(input:{error:unknown;event:NavigationEvent;status:number;message:string;})=>MaybePromise<void|App.Error>
The client-sidehandleError
hook runs when an unexpected error is thrown while navigating.
If an unexpected error is thrown during loading or the following render, this function will be called with the error and the event.Make sure that this functionnever throws an error.
HandleClientError}from'@sveltejs/kit';module"@sentry/sveltekit"
Sentry.constinit:(opts:any)=>void
init({/*...*/})exportconstconsthandleError:HandleClientError
handleError:typeHandleClientError=(input:{error:unknown;event:NavigationEvent;status:number;message:string;})=>MaybePromise<void|App.Error>
The client-sidehandleError
hook runs when an unexpected error is thrown while navigating.
If an unexpected error is thrown during loading or the following render, this function will be called with the error and the event.Make sure that this functionnever throws an error.
HandleClientError=async({error:unknown
error,event:NavigationEvent<Partial<Record<string,string>>,string|null>
event,status:number
status,message:string
message})=>{constconsterrorId:`${string}-${string}-${string}-${string}-${string}`
errorId=varcrypto:Crypto
crypto.Crypto.randomUUID():`${string}-${string}-${string}-${string}-${string}`
Available only in secure contexts.
randomUUID();// example integration with https://sentry.io/module"@sentry/sveltekit"
Sentry.constcaptureException:(error:any,opts:any)=>void
captureException(error:unknown
error,{extra:{event:NavigationEvent<Partial<Record<string,string>>,string|null>;errorId:`${string}-${string}-${string}-${string}-${string}`;status:number;}
extra:{event:NavigationEvent<Partial<Record<string,string>>,string|null>
event,errorId:`${string}-${string}-${string}-${string}-${string}`
errorId,status:number
status}});return{App.Error.message: string
message:'Whoops!',errorId:`${string}-${string}-${string}-${string}-${string}`
errorId};};
In
src/hooks.client.js
, the type ofhandleError
isHandleClientError
instead ofHandleServerError
, andevent
is aNavigationEvent
rather than aRequestEvent
.
This function is not called forexpected errors (those thrown with theerror
function imported from@sveltejs/kit
).
During development, if an error occurs because of a syntax error in your Svelte code, the passed in error has aframe
property appended highlighting the location of the error.
Make sure that
handleError
never throws an error
init
This function runs once, when the server is created or the app starts in the browser, and is a useful place to do asynchronous work such as initializing a database connection.
If your environment supports top-level await, the
init
function is really no different from writing your initialisation logic at the top level of the module, but some environments — most notably, Safari — don’t.
import*asimportdb
dbfrom'$lib/server/database';/**@type{import('@sveltejs/kit').ServerInit}*/exportasyncfunctionfunctioninit():Promise<void>
@type{import('@sveltejs/kit').ServerInit}init() {awaitimportdb
db.connect();}
import*asimportdb
dbfrom'$lib/server/database';importtype{typeServerInit=()=>MaybePromise<void>
Theinit
will be invoked before the server responds to its first request
@since2.10.0ServerInit}from'@sveltejs/kit';exportconstconstinit:ServerInit
init:typeServerInit=()=>MaybePromise<void>
Theinit
will be invoked before the server responds to its first request
@since2.10.0ServerInit=async()=>{awaitimportdb
db.connect();};
In the browser, asynchronous work in
init
will delay hydration, so be mindful of what you put in there.
Universal hooks
The following can be added tosrc/hooks.js
. Universal hooks run on both server and client (not to be confused with shared hooks, which are environment-specific).
reroute
This function runs beforehandle
and allows you to change how URLs are translated into routes. The returned pathname (which defaults tourl.pathname
) is used to select the route and its parameters.
For example, you might have asrc/routes/[[lang]]/about/+page.svelte
page, which should be accessible as/en/about
or/de/ueber-uns
or/fr/a-propos
. You could implement this withreroute
:
/**@type{Record<string, string>}*/constconsttranslated:{'/en/about':string;'/de/ueber-uns':string;'/fr/a-propos':string;}
@type{Record<string, string>}translated={'/en/about':'/en/about','/de/ueber-uns':'/de/about','/fr/a-propos':'/fr/about',};/**@type{import('@sveltejs/kit').Reroute}*/exportfunctionfunctionreroute({ url }:{url:any;}):any
@type{import('@sveltejs/kit').Reroute}reroute({url:any
url}) {if(url:any
url.pathnameinconsttranslated:{'/en/about':string;'/de/ueber-uns':string;'/fr/a-propos':string;}
@type{Record<string, string>}translated) {returnconsttranslated:{'/en/about':string;'/de/ueber-uns':string;'/fr/a-propos':string;}
@type{Record<string, string>}translated[url:any
url.pathname];}}
importtype{typeReroute=(event:{url:URL;fetch:typeoffetch;})=>MaybePromise<string|void>
Thereroute
hook allows you to modify the URL before it is used to determine which route to render.
@since2.3.0Reroute}from'@sveltejs/kit';constconsttranslated:Record<string,string>
translated:typeRecord<Kextendskeyofany,T>={ [PinK]:T; }
Construct a type with a set of properties K of type T
Record<string,string>={'/en/about':'/en/about','/de/ueber-uns':'/de/about','/fr/a-propos':'/fr/about',};exportconstconstreroute:Reroute
reroute:typeReroute=(event:{url:URL;fetch:typeoffetch;})=>MaybePromise<string|void>
Thereroute
hook allows you to modify the URL before it is used to determine which route to render.
@since2.3.0Reroute=({url:URL
url})=>{if(url:URL
url.URL.pathname: string
pathnameinconsttranslated:Record<string,string>
translated) {returnconsttranslated:Record<string,string>
translated[url:URL
url.URL.pathname: string
pathname];}};
Thelang
parameter will be correctly derived from the returned pathname.
Usingreroute
willnot change the contents of the browser’s address bar, or the value ofevent.url
.
Since version 2.18, thereroute
hook can be asynchronous, allowing it to (for example) fetch data from your backend to decide where to reroute to. Use this carefully and make sure it’s fast, as it will delay navigation otherwise. If you need to fetch data, use thefetch
provided as an argument. It has thesame benefits as thefetch
provided toload
functions, with the caveat thatparams
andid
are unavailable tohandleFetch
because the route is not yet known.
/**@type{import('@sveltejs/kit').Reroute}*/exportfunctionfunctionreroute({ url,fetch }:{url:any;fetch:any;}):any
@type{import('@sveltejs/kit').Reroute}reroute({url:any
url,fetch:any
fetch}) {// Ask a special endpoint within your app about the destinationif(url:any
url.pathname==='/api/reroute')return;constconstapi:URL
api=newvarURL:new(url:string|URL,base?:string|URL)=>URL
The URL interface represents an object providing static methods used for creating object URLs.
URL
class is a global reference forrequire('url').URL
https://nodejs.org/api/url.html#the-whatwg-url-api
@sincev10.0.0URL('/api/reroute',url:any
url);constapi:URL
api.URL.searchParams: URLSearchParams
searchParams.URLSearchParams.set(name: string,value: string):void
Sets the value associated to a given search parameter to the given value. If there were several values, delete the others.
set('pathname',url:any
url.pathname);constconstresult:any
result=awaitfetch:any
fetch(constapi:URL
api).then(r:any
r=>r:any
r.json());returnconstresult:any
result.pathname;}
importtype{typeReroute=(event:{url:URL;fetch:typeoffetch;})=>MaybePromise<string|void>
Thereroute
hook allows you to modify the URL before it is used to determine which route to render.
@since2.3.0Reroute}from'@sveltejs/kit';exportconstconstreroute:Reroute
reroute:typeReroute=(event:{url:URL;fetch:typeoffetch;})=>MaybePromise<string|void>
Thereroute
hook allows you to modify the URL before it is used to determine which route to render.
@since2.3.0Reroute=({url:URL
url,fetch:{(input:RequestInfo|URL,init?:RequestInit):Promise<Response>;(input:string|URL|globalThis.Request,init?:RequestInit):Promise<Response>;}
fetch})=>{// Ask a special endpoint within your app about the destinationif(url:URL
url.URL.pathname: string
pathname==='/api/reroute')return;constconstapi:URL
api=newvarURL:new(url:string|URL,base?:string|URL)=>URL
The URL interface represents an object providing static methods used for creating object URLs.
URL
class is a global reference forrequire('url').URL
https://nodejs.org/api/url.html#the-whatwg-url-api
@sincev10.0.0URL('/api/reroute',url:URL
url);constapi:URL
api.URL.searchParams: URLSearchParams
searchParams.URLSearchParams.set(name: string,value: string):void
Sets the value associated to a given search parameter to the given value. If there were several values, delete the others.
set('pathname',url:URL
url.URL.pathname: string
pathname);constconstresult:any
result=awaitfetch:(input:string|URL|globalThis.Request,init?:RequestInit)=>Promise<Response> (+1overload)
fetch(constapi:URL
api).Promise<Response>.then<any,never>(onfulfilled?:((value:Response)=>any)|null|undefined,onrejected?:((reason:any)=>PromiseLike<never>)|null|undefined):Promise<any>
Attaches callbacks for the resolution and/or rejection of the Promise.
@paramonfulfilled The callback to execute when the Promise is resolved.@paramonrejected The callback to execute when the Promise is rejected.@returnsA Promise for the completion of which ever callback is executed.then(r:Response
r=>r:Response
r.Body.json():Promise<any>
json());returnconstresult:any
result.pathname;};
reroute
is considered a pure, idempotent function. As such, it must always return the same output for the same input and not have side effects. Under these assumptions, SvelteKit caches the result ofreroute
on the client so it is only called once per unique URL.
transport
This is a collection oftransporters, which allow you to pass custom types — returned fromload
and form actions — across the server/client boundary. Each transporter contains anencode
function, which encodes values on the server (or returnsfalse
for anything that isn’t an instance of the type) and a correspondingdecode
function:
import{importVector
Vector}from'$lib/math';/**@type{import('@sveltejs/kit').Transport}*/exportconstconsttransport:{Vector:{encode:(value:any)=>false|any[];decode:([x,y]:[any,any])=>any;};}
@type{import('@sveltejs/kit').Transport}transport={typeVector: {encode: (value: any)=>false|any[];decode:([x,y]:[any,any])=>any;}
Vector:{encode:(value:any)=>false|any[]
encode:(value:any
value)=>value:any
valueinstanceofimportVector
Vector&&[value:any
value.x,value:any
value.y],decode:([x,y]:[any,any])=>any
decode:([x:any
x,y:any
y])=>newimportVector
Vector(x:any
x,y:any
y)}};
import{importVector
Vector}from'$lib/math';importtype{typeTransport={[x:string]:Transporter<any,any>;}
Thetransport
hook allows you to transport custom types across the server/client boundary.
Each transporter has a pair ofencode
anddecode
functions. On the server,encode
determines whether a value is an instance of the custom type and, if so, returns a non-falsy encoding of the value which can be an object or an array (orfalse
otherwise).
In the browser,decode
turns the encoding back into an instance of the custom type.
importtype{ Transport }from'@sveltejs/kit';declareclassMyCustomType{data:any}// hooks.jsexportconsttransport:Transport={MyCustomType:{encode:(value)=>valueinstanceofMyCustomType&& [value.data],decode:([data])=>newMyCustomType(data)}};
@since2.11.0Transport}from'@sveltejs/kit';exportconstconsttransport:Transport
transport:typeTransport={[x:string]:Transporter<any,any>;}
Thetransport
hook allows you to transport custom types across the server/client boundary.
Each transporter has a pair ofencode
anddecode
functions. On the server,encode
determines whether a value is an instance of the custom type and, if so, returns a non-falsy encoding of the value which can be an object or an array (orfalse
otherwise).
In the browser,decode
turns the encoding back into an instance of the custom type.
importtype{ Transport }from'@sveltejs/kit';declareclassMyCustomType{data:any}// hooks.jsexportconsttransport:Transport={MyCustomType:{encode:(value)=>valueinstanceofMyCustomType&& [value.data],decode:([data])=>newMyCustomType(data)}};
@since2.11.0Transport={typeVector: {encode: (value: any)=>false|any[];decode:([x,y]:any)=>any;}
Vector:{Transporter<any,any>.encode: (value:any)=>any
encode:(value:any
value)=>value:any
valueinstanceofimportVector
Vector&&[value:any
value.x,value:any
value.y],Transporter<any,any>.decode: (data:any)=>any
decode:([x:any
x,y:any
y])=>newimportVector
Vector(x:any
x,y:any
y)}};