The @sveltejs/adapter-node adapter generates a standalone Node server for your SvelteKit application.
Installation
npm install -D @sveltejs/adapter-node
Usage
Add the adapter to your svelte.config.js:
/// file: svelte.config.js
import adapter from '@sveltejs/adapter-node' ;
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter ({
// Adapter options
out: 'build' ,
precompress: true ,
envPrefix: ''
})
}
};
export default config ;
Configuration options
These options are defined in the adapter source code:
/// file: packages/adapter-node/index.d.ts
interface AdapterOptions {
out ?: string ; // Output directory (default: 'build')
precompress ?: boolean ; // Enable gzip/brotli compression (default: true)
envPrefix ?: string ; // Environment variable prefix (default: '')
}
out
The directory where the server build output will be written.
adapter ({
out: 'my-server-build'
})
precompress
Enables precompression of assets using gzip and brotli. This is enabled by default.
adapter ({
precompress: true // Creates .gz and .br files alongside assets
})
From the adapter implementation:
/// file: packages/adapter-node/index.js
if ( precompress ) {
builder . log . minor ( 'Compressing assets' );
await Promise . all ([
builder . compress ( ` ${ out } /client` ),
builder . compress ( ` ${ out } /prerendered` )
]);
}
envPrefix
A prefix for environment variables. For example, if you set envPrefix: 'MY_APP_', then environment variables like MY_APP_HOST and MY_APP_PORT will be used.
adapter ({
envPrefix: 'MY_APP_'
})
Deployment
After building your app, the output directory contains everything needed to run your application:
Environment variables
The adapter recognizes several environment variables to configure the server at runtime:
Variable Description Default PORTPort to listen on 3000HOSTHost to listen on 0.0.0.0ORIGINOrigin URL for the app Auto-detected XFF_DEPTHDepth of X-Forwarded-For header to trust 1ADDRESS_HEADERHeader to read client address from - PROTOCOL_HEADERHeader to read protocol from - HOST_HEADERHeader to read host from - PORT_HEADERHeader to read port from - BODY_SIZE_LIMITMaximum request body size 512K
Basic usage
Behind a proxy
Custom origin
PORT = 4000 node build/index.js
Here’s how environment variables are used in the handler:
/// file: packages/adapter-node/src/handler.js
const origin = parse_origin ( env ( 'ORIGIN' , undefined ));
const xff_depth = parseInt ( env ( 'XFF_DEPTH' , '1' ));
const address_header = env ( 'ADDRESS_HEADER' , '' ). toLowerCase ();
const protocol_header = env ( 'PROTOCOL_HEADER' , '' ). toLowerCase ();
const host_header = env ( 'HOST_HEADER' , '' ). toLowerCase ();
const port_header = env ( 'PORT_HEADER' , '' ). toLowerCase ();
const body_size_limit = parse_as_bytes ( env ( 'BODY_SIZE_LIMIT' , '512K' ));
Build output structure
The adapter generates the following directory structure:
build/
├── index.js # Server entry point
├── handler.js # Request handler
├── env.js # Environment configuration
├── server/ # Server-side code
│ ├── index.js # SvelteKit server
│ └── manifest.js # App manifest
├── client/ # Client assets
│ └── _app/ # Built client code
└── prerendered/ # Prerendered pages
The adapter provides access to the raw Node.js request object via event.platform:
/// file: src/hooks.server.js
/** @type {import('@sveltejs/kit').Handle} */
export async function handle ({ event , resolve }) {
// Access the raw Node request
const { req } = event . platform ;
console . log ( 'Request headers:' , req . headers );
return resolve ( event );
}
The platform.req object is the raw Node.js IncomingMessage object from the http module.
Advanced usage
You can use the generated handler.js as middleware in your own Node server:
import express from 'express' ;
import { handler } from './build/handler.js' ;
const app = express ();
// Add custom middleware
app . use ( '/api/custom' , ( req , res ) => {
res . json ({ custom: 'endpoint' });
});
// Use SvelteKit handler for everything else
app . use ( handler );
app . listen ( 3000 );
The adapter bundles dependencies using Rollup, but dependencies listed in package.json are kept as external imports. Make sure to install production dependencies before deploying.