SvelteKit on Cloudflare Workers
SvelteKit is the full-stack framework for Svelte. It uses adapter-cloudflare for Workers deployment. The dev server runs in Node.js (no CF Vite Plugin), so there’s a gap between dev and prod environments.
Create a New Project
npm create cloudflare@latest my-svelte-app -- --framework=svelte
Or add Cloudflare to an existing SvelteKit project:
npm install -D @sveltejs/adapter-cloudflare
Project Structure
my-svelte-app/
├── src/
│ ├── routes/
│ │ ├── +page.svelte # Page component
│ │ ├── +page.server.ts # Server-side data loading
│ │ └── +layout.svelte # Layout
│ └── app.html # HTML template
├── svelte.config.js # SvelteKit + adapter config
└── wrangler.jsonc # Cloudflare config
SvelteKit Config
// svelte.config.js
import adapter from "@sveltejs/adapter-cloudflare";
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte";
export default {
preprocess: vitePreprocess(),
kit: {
adapter: adapter(),
},
};
Gotcha:
adapter-cloudflare-workersis deprecated. Useadapter-cloudflare(without the-workerssuffix). The deprecated package targeted the old Workers Sites, not Workers Static Assets.
Page with Server Data
<!-- src/routes/+page.svelte -->
<script>
let { data } = $props();
</script>
<h1>Welcome</h1>
<p>Visits: {data.visits}</p>
// src/routes/+page.server.ts
import type { PageServerLoad } from "./$types";
export const load: PageServerLoad = async ({ platform }) => {
const visits = await platform?.env?.MY_KV?.get("visits");
return { visits: Number(visits || 0) };
};
API Route
// src/routes/api/hello/+server.ts
import type { RequestHandler } from "./$types";
export const GET: RequestHandler = async ({ platform }) => {
const value = await platform?.env?.MY_KV?.get("greeting");
return new Response(JSON.stringify({ message: value || "Hello" }), {
headers: { "content-type": "application/json" },
});
};
Binding Types
Generate types from your wrangler config:
npx wrangler types
Then reference them in src/app.d.ts:
// src/app.d.ts
declare global {
namespace App {
interface Platform {
env: {
MY_KV: KVNamespace;
MY_DB: D1Database;
};
}
}
}
export {};
Dev and Deploy
# Development (Node.js - no workerd parity)
npm run dev
# Build
npm run build
# Preview with wrangler (runs in workerd)
npx wrangler pages dev .svelte-kit/cloudflare
# Deploy
npx wrangler deploy
Tip: Always test with
wrangler pages devbefore deploying. The Node.js dev server won’t catchworkerdruntime issues.
Key Points
platform.envgives you access to Cloudflare bindings- File-based routing in
src/routes/ +page.server.tsruns on the server,+page.svelterenders the component- Dev runs in Node.js, not
workerd(no CF Vite Plugin integration yet) adapter-cloudflaretargets Workers Static Assets- Svelte 5 runes (
$state,$derived,$effect) work fine on Cloudflare
Gotcha:
platformisundefinedduringnpm run devsince there’s noworkerdruntime. Use optional chaining (platform?.env?.MY_KV) or mock bindings in dev.