pnpx sv create my-app
cd my-app
pnpm install
pnpx sv create my-app
cd my-app
pnpm install
pnpx sv create my-app
cd my-app
pnpm install
pnpm add -D @sveltejs/adapter-cloudflare
pnpm add -D @sveltejs/adapter-cloudflare
pnpm add -D @sveltejs/adapter-cloudflare
import adapter from '@sveltejs/adapter-cloudflare';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; /** @type {import('@sveltejs/kit').Config} */
const config = { preprocess: vitePreprocess(), kit: { adapter: adapter({ // See below for options config: undefined, platformProxy: { configPath: undefined, environment: undefined, persist: undefined }, fallback: 'plaintext', routes: { include: ['/*'], exclude: ['<files>', '<build>', '<redirects>'] } }) }
}; export default config;
import adapter from '@sveltejs/adapter-cloudflare';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; /** @type {import('@sveltejs/kit').Config} */
const config = { preprocess: vitePreprocess(), kit: { adapter: adapter({ // See below for options config: undefined, platformProxy: { configPath: undefined, environment: undefined, persist: undefined }, fallback: 'plaintext', routes: { include: ['/*'], exclude: ['<files>', '<build>', '<redirects>'] } }) }
}; export default config;
import adapter from '@sveltejs/adapter-cloudflare';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; /** @type {import('@sveltejs/kit').Config} */
const config = { preprocess: vitePreprocess(), kit: { adapter: adapter({ // See below for options config: undefined, platformProxy: { configPath: undefined, environment: undefined, persist: undefined }, fallback: 'plaintext', routes: { include: ['/*'], exclude: ['<files>', '<build>', '<redirects>'] } }) }
}; export default config;
{ "name": "my-sveltekit-app", "main": ".svelte-kit/cloudflare/_worker.js", "compatibility_flags": ["nodejs_als", "nodejs_compat"], "compatibility_date": "2024-09-23", "assets": { "binding": "ASSETS", "directory": ".svelte-kit/cloudflare" }, "routes": [ { "pattern": "yourdomain.com", "custom_domain": true } ]
}
{ "name": "my-sveltekit-app", "main": ".svelte-kit/cloudflare/_worker.js", "compatibility_flags": ["nodejs_als", "nodejs_compat"], "compatibility_date": "2024-09-23", "assets": { "binding": "ASSETS", "directory": ".svelte-kit/cloudflare" }, "routes": [ { "pattern": "yourdomain.com", "custom_domain": true } ]
}
{ "name": "my-sveltekit-app", "main": ".svelte-kit/cloudflare/_worker.js", "compatibility_flags": ["nodejs_als", "nodejs_compat"], "compatibility_date": "2024-09-23", "assets": { "binding": "ASSETS", "directory": ".svelte-kit/cloudflare" }, "routes": [ { "pattern": "yourdomain.com", "custom_domain": true } ]
}
pnpm add -g wrangler
wrangler login
wrangler deploy
pnpm add -g wrangler
wrangler login
wrangler deploy
pnpm add -g wrangler
wrangler login
wrangler deploy
// +page.server.js
import { SECRET_API_KEY } from '$env/static/private'; export async function load() { // Use SECRET_API_KEY here
}
// +page.server.js
import { SECRET_API_KEY } from '$env/static/private'; export async function load() { // Use SECRET_API_KEY here
}
// +page.server.js
import { SECRET_API_KEY } from '$env/static/private'; export async function load() { // Use SECRET_API_KEY here
}
// hooks.js or +server.js
export async function handle({ event, resolve }) { const { env } = event.platform; // env.MY_KV_NAMESPACE, env.MY_DURABLE_OBJECT, etc. return resolve(event);
}
// hooks.js or +server.js
export async function handle({ event, resolve }) { const { env } = event.platform; // env.MY_KV_NAMESPACE, env.MY_DURABLE_OBJECT, etc. return resolve(event);
}
// hooks.js or +server.js
export async function handle({ event, resolve }) { const { env } = event.platform; // env.MY_KV_NAMESPACE, env.MY_DURABLE_OBJECT, etc. return resolve(event);
}
pnpm build
wrangler dev .svelte-kit/cloudflare/_worker.js
pnpm build
wrangler dev .svelte-kit/cloudflare/_worker.js
pnpm build
wrangler dev .svelte-kit/cloudflare/_worker.js
# .github/workflows/deploy.yml
name: Deploy
on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: pnpm install - run: pnpm build - run: pnpx wrangler deploy env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
# .github/workflows/deploy.yml
name: Deploy
on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: pnpm install - run: pnpm build - run: pnpx wrangler deploy env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
# .github/workflows/deploy.yml
name: Deploy
on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 - run: pnpm install - run: pnpm build - run: pnpx wrangler deploy env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} - 100,000 requests/day — enough for most personal projects and small sites
- 10ms CPU time per request — SvelteKit runs comfortably within this
- 1 GB of KV storage — for simple config or session data
- Custom domains — connect your own domain at no extra cost - Node.js 18+ installed
- A Cloudflare account (free tier works fine)
- A SvelteKit project ready to deploy - config: Path to your Wrangler config file (we'll create this next)
- platformProxy: Controls how local bindings are emulated during development
- fallback: 'plaintext' gives you a simple 404 page; use 'spa' if you need client-side routing for unmatched paths
- routes.exclude: Tells Cloudflare which requests can bypass the Worker and serve static assets directly. This saves you invocation costs. - name: Your Worker's identifier in the Cloudflare dashboard
- main: The entry point SvelteKit generates. Don't change this.
- compatibility_flags: nodejs_als is required for SvelteKit's async context; nodejs_compat helps with NPM packages that use Node.js APIs
- compatibility_date: Cloudflare's runtime version. Bump this periodically for new features.
- assets: Tells Workers where your static files live
- routes: Connects custom domains (you can add this later if you don't have a domain yet) - Go to Workers & Pages in your Cloudflare dashboard
- Select your Worker
- Click "Triggers" → "Add Custom Domain"
- Enter your domain - Check for large dependencies bundled on the server side
- Move heavy libraries to client-only imports if possible
- Use dynamic imports for code splitting - Requests: Free tier = 100k/day. At ~10k requests/day, you've got a 10-day buffer.
- CPU time: SvelteKit usually runs under 5ms per request unless you're doing heavy computation. - Prerendering more pages at build time
- Caching API responses at the edge
- Using KV for frequently-read, rarely-written data