SvelteKit SSR
Copy it into a new project:
pnpm dlx degit antstanley/blogwright/examples/sveltekit-ssr my-siteSvelteKit with adapter-node, running on a Lambda Web Function. Fingerprinted /_app/ assets still serve from S3.
| Framework | Mode | Blogwright config | Source |
|---|---|---|---|
SvelteKit + adapter-node |
Server-rendered | ssr |
examples/sveltekit-ssr |
Deploy it
Section titled “Deploy it”-
Copy the example and start a repository:
Terminal window pnpm dlx degit antstanley/blogwright/examples/sveltekit-ssr my-sitecd my-site && git init -
Set
siteNameandregioninconfig/production.jsonc. For SSR,regionmust beus-east-1,us-east-2,us-west-2,ap-northeast-1oreu-west-1. -
Add Blogwright, then commit everything, including
pnpm-lock.yaml- the builder installs with--frozen-lockfile:Terminal window pnpm add -D blogwrightgit add -A && git commit -m "Start from the blogwright example" -
Create the infrastructure:
pnpm exec blogwright bootstrap -
Build and publish:
pnpm exec blogwright deploy
What matters
Section titled “What matters”vite.config.js-adapter-node, andpaths.originset to the public origin. The app receives the endpoint’s domain asHost, so without it SvelteKit’s CSRF check rejects form actions (Cross-site POST form submissions are forbidden). Replacehttps://example.comwith your domain.package.json- every package is adevDependency, soadapter-nodebundles it intobuild/and the package needs nonode_modules. A package underdependenciesstays an import and would have to be installed intobuild/node_modulesas real files.lambda.mjs- the entry shim. It mapsAWS_LAMBDA_HTTP_ENDPOINTontoHOSTandPORT, then importsindex.js. The build copies it intobuild/. Blogwright can generate this shim instead: deletelambda.mjsand the build step that copies it, and set"entryPoint": "index.js"with"shim": { "host": "HOST", "port": "PORT" }in thessrblock. See the entry shim.config/production.jsonc- packagesbuild/.staticDirandstaticPathspublish the fingerprinted/_app/assets to S3.
The files
Section titled “The files”// Blogwright config for this example. Paths are relative to the repository// root, so they assume this directory IS the repository - see README.md.{ "region": "us-east-1", "siteName": "sveltekit-ssr", "ssr": { "packageDir": "build", "entryPoint": "lambda.mjs", "staticDir": "build/client", "staticPaths": ["/_app/*", "/favicon.svg"], },}import adapter from '@sveltejs/adapter-node';import { sveltekit } from '@sveltejs/kit/vite';import { defineConfig } from 'vite';
export default defineConfig({ plugins: [ sveltekit({ adapter: adapter(), paths: { // The app sees the Web Function endpoint's domain as Host, so form // actions need the public origin to pass SvelteKit's CSRF check. origin: 'https://example.com', }, }), ],});// Entry shim for Lambda Web Functions. Lambda passes the listen address in// AWS_LAMBDA_HTTP_ENDPOINT; adapter-node's server reads HOST and PORT.const endpoint = process.env.AWS_LAMBDA_HTTP_ENDPOINT;const colon = endpoint.lastIndexOf(':');process.env.HOST = endpoint.slice(0, colon);process.env.PORT = endpoint.slice(colon + 1);await import('./index.js');{ "name": "blogwright-example-sveltekit-ssr", "private": true, "type": "module", "packageManager": "pnpm@11.25.0", "scripts": { "dev": "vite dev", "build": "vite build && cp lambda.mjs build/", "preview": "vite preview" }, "devDependencies": { "@sveltejs/adapter-node": "^6.0.0", "@sveltejs/kit": "^3.0.1", "svelte": "^5.57.2", "vite": "^8.3.4" }}Check the package locally
Section titled “Check the package locally”Run it the way Lambda does - from a copy outside the project, so nothing resolves from its own node_modules:
pnpm buildcp -R build /tmp/pkg && cd /tmp/pkgAWS_LAMBDA_HTTP_ENDPOINT=127.0.0.1:8080 node lambda.mjscurl -i http://127.0.0.1:8080/The server must start listening within 10 seconds, and find build -type l must print nothing: the build agent rejects a package that contains a symbolic link.
Related pages
Section titled “Related pages”- Server-rendered sites: SvelteKit - the full recipe and its options
- Examples overview - every example, and the conventions they share