Skip to main content

Writing adapters

If an adapter for your preferred environment doesn't yet exist, you can build your own. We recommend looking at the source for an adapter to a platform similar to yours and copying it as a starting point.

Adapter packages implement the following API, which creates an Adapter:

/** @param {AdapterSpecificOptions} options */
export default function (options: any
@param
options
options
) {
/** @type {import('@sveltejs/kit').Adapter} */ const const adapter: Adapteradapter = { Adapter.name: string

The name of the adapter, using for logging. Will typically correspond to the package name.

name
: 'adapter-package-name',
async Adapter.adapt: (builder: Builder) => MaybePromise<void>

This function is called after SvelteKit has built your app.

@param
builder An object provided by SvelteKit that contains methods for adapting the app
adapt
(builder: Builderbuilder) {
// adapter implementation }, async Adapter.emulate?: (() => MaybePromise<Emulator>) | undefined

Creates an Emulator, which allows the adapter to influence the environment during dev, build and prerendering.

emulate
() {
return { async
Emulator.platform?(details: {
    config: any;
    prerender: PrerenderOption;
}): MaybePromise<App.Platform>

A function that is called with the current route config and prerender option and returns an App.Platform object

platform
({ config: anyconfig, prerender: PrerenderOptionprerender }) {
// the returned object becomes `event.platform` during dev, build and // preview. Its shape is that of `App.Platform` } } },
Adapter.supports?: {
    read?: (details: {
        config: Record<string, any>;
        route: {
            id: string;
        };
    }) => boolean;
    instrumentation?: () => boolean;
} | undefined

Checks called during dev and build to determine whether specific features will work in production with this adapter.

supports
: {
read: ({ config: Record<string, any>config,
route: {
    id: string;
}
route
}) => {
// Return `true` if the route with the given `config` can use `read` // from `$app/server` in production, return `false` if it can't. // Or throw a descriptive error describing how to configure the deployment }, instrumentation: () => { // Return `true` if this adapter supports loading `instrumentation.server.js`. // Return `false if it can't, or throw a descriptive error. } }, // Specify the path of a module to customise request handling Adapter.customHandler?: string | undefined

The path to a module whose default export is a custom handler.

@since
3.0.0
customHandler
: import.meta.ImportMeta.resolve(specifier: string, parent?: string | URL): string (+1 overload)

import.meta.resolve is a module-relative resolution function scoped to each module, returning the URL string.

const dependencyAsset = import.meta.resolve('component-lib/asset.css');
// file:///app/node_modules/component-lib/asset.css
import.meta.resolve('./dep.js');
// file:///app/dep.js

All features of the Node.js module resolution are supported. Dependency resolutions are subject to the permitted exports resolutions within the package.

Caveats:

  • This can result in synchronous file-system operations, which can impact performance similarly to require.resolve.
  • This feature is not available within custom loaders (it would create a deadlock).
@since
v13.9.0, v12.16.0
@param
specifier The module specifier to resolve relative to the current module.
@param
parent An optional absolute parent module URL to resolve from. Default: import.meta.url
@returns
The absolute URL string that the specifier would resolve to.
resolve
('./handler.js'),
Adapter.vite?: {
    plugins?: Plugin[];
} | undefined
vite
: {
plugins?: Plugin<any>[] | undefined

Plugins provided by the adapter are placed before any of SvelteKit's own plugins.

@since
3.0.0
plugins
: [
// add plugins here to integrate with Vite ] } }; return const adapter: Adapter
adapter
;
}

Of these, name and adapt are required. emulate, customHandler, vite.plugins and supports are optional.

Within the adapt method, there are a number of things that an adapter should do:

  • Clear out the build directory
  • Write SvelteKit output with builder.writeClient, builder.writeServer, and builder.writePrerendered
  • Output code that:
    • Imports Server from ${builder.getServerDirectory()}/index.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 server.respond(request, { getClientAddress }) function to generate a Response and responds with it
    • expose any platform-specific information to SvelteKit via the platform option passed to server.respond
  • 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].

Custom request handler

You can customise your server's initialisation and request handling by adding a customHandler property resolved to the path of your handler file.

/** @param {AdapterSpecificOptions} options */
export default function (options: any
@param
options
options
) {
/** @type {import('@sveltejs/kit').Adapter} */ const const adapter: Adapteradapter = { Adapter.name: string

The name of the adapter, using for logging. Will typically correspond to the package name.

name
: 'adapter-package-name',
async Adapter.adapt: (builder: Builder) => MaybePromise<void>

This function is called after SvelteKit has built your app.

@param
builder An object provided by SvelteKit that contains methods for adapting the app
adapt
(builder: Builderbuilder) {
// adapter implementation }, Adapter.customHandler?: string | undefined

The path to a module whose default export is a custom handler.

@since
3.0.0
customHandler
: import.meta.ImportMeta.resolve(specifier: string, parent?: string | URL): string (+1 overload)

import.meta.resolve is a module-relative resolution function scoped to each module, returning the URL string.

const dependencyAsset = import.meta.resolve('component-lib/asset.css');
// file:///app/node_modules/component-lib/asset.css
import.meta.resolve('./dep.js');
// file:///app/dep.js

All features of the Node.js module resolution are supported. Dependency resolutions are subject to the permitted exports resolutions within the package.

Caveats:

  • This can result in synchronous file-system operations, which can impact performance similarly to require.resolve.
  • This feature is not available within custom loaders (it would create a deadlock).
@since
v13.9.0, v12.16.0
@param
specifier The module specifier to resolve relative to the current module.
@param
parent An optional absolute parent module URL to resolve from. Default: import.meta.url
@returns
The absolute URL string that the specifier would resolve to.
resolve
('./src/handler.js')
} return const adapter: Adapter
adapter
;
};

The handler file should export a default function that returns a request handler. The should return a Response such as by calling server.respond along with any platform-specific context.

src/handler
/** @type {import('@sveltejs/kit').SSRHandler} */
export default async function 
function handler(server: {
    respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}): MaybePromise<(request: Request) => MaybePromise<Response>>
handler
(
server: {
    respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}
server
) {
// perform setup work here return async (request: Requestrequest) => { // custom request/response handling logic goes here if (new var URL: new (url: string | URL, base?: string | URL) => URL

The URL interface is used to parse, construct, normalize, and encode URLs. It works by providing properties which allow you to easily read and modify the components of a URL.

MDN Reference

URL class is a global reference for import { URL } from 'url' https://nodejs.org/api/url.html#the-whatwg-url-api

@since
v10.0.0
URL
(request: Requestrequest.Request.url: string

The url read-only property of the Request interface contains the URL of the request.

MDN Reference

url
).URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure. It is a string constructed from a list of path segments, each of which is prefixed by a / character.

MDN Reference

pathname
=== '/_ping') {
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response

The Response interface of the Fetch API represents the response to a request.

MDN Reference

Response
('pong');
} return await
server: {
    respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}
server
.respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>respond(request: Requestrequest, {
platform?: App.Platform | undefinedplatform: { // the shape of `App.Platform` } }); }; }
import type { 
type SSRHandler = (server: {
    respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}) => MaybePromise<(request: Request) => MaybePromise<Response>>

The custom handler an adapter can specify to customise request handling. It is expected to return a function which returns a Response or calls server.respond with any platform-specific context.

@since
3.0.0
SSRHandler
} from '@sveltejs/kit';
export const const handler: SSRHandlerhandler:
type SSRHandler = (server: {
    respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}) => MaybePromise<(request: Request) => MaybePromise<Response>>

The custom handler an adapter can specify to customise request handling. It is expected to return a function which returns a Response or calls server.respond with any platform-specific context.

@since
3.0.0
SSRHandler
= async (
server: {
    respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}
server
) => {
// perform setup work here return async (request: Requestrequest) => { // custom request/response handling logic goes here if (new var URL: new (url: string | URL, base?: string | URL) => URL

The URL interface is used to parse, construct, normalize, and encode URLs. It works by providing properties which allow you to easily read and modify the components of a URL.

MDN Reference

URL class is a global reference for import { URL } from 'url' https://nodejs.org/api/url.html#the-whatwg-url-api

@since
v10.0.0
URL
(request: Requestrequest.Request.url: string

The url read-only property of the Request interface contains the URL of the request.

MDN Reference

url
).URL.pathname: string

The pathname property of the URL interface represents a location in a hierarchical structure. It is a string constructed from a list of path segments, each of which is prefixed by a / character.

MDN Reference

pathname
=== '/_ping') {
return new var Response: new (body?: BodyInit | null, init?: ResponseInit) => Response

The Response interface of the Fetch API represents the response to a request.

MDN Reference

Response
('pong');
} return await
server: {
    respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}
server
.respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>respond(request: Requestrequest, {
platform?: App.Platform | undefinedplatform: { // the shape of `App.Platform` } }); }; };

Edit this page on GitHub llms.txt

previous next