Complete guide to deploying your SvelteKit frontend on Cloudflare Pages. Includes edge functions, global CDN, and privacy-focused deployment.
Deploying SvelteKit to Cloudflare Pages
Cloudflare Pages is a powerful, privacy-focused platform for deploying SvelteKit applications. With a global CDN, edge functions, and generous free tier, it's an excellent choice for hosting your frontend.
Why Cloudflare Pages?
- Privacy-first: Cloudflare does not use your data for AI training
- Global CDN: 300+ locations worldwide for fast load times
- Edge functions: Run code at the edge (Cloudflare Workers runtime)
- Generous free tier: Unlimited bandwidth, 500 builds/month
- Git integration: Automatic deployments from GitHub/GitLab
- Custom domains: Free SSL with automatic renewal
Prerequisites
- Git repository with SvelteKit code
- Cloudflare account (free tier available)
- Node.js 20+ installed
Install Development Tools
We recommend using mise (version manager) and pnpm (package manager) instead of npm:
Install mise:
curl https://mise.run | sh
# Add to your shell (follow post-install instructions)
echo 'eval "$(mise activate)"' >> ~/.bashrc
# or for zsh
echo 'eval "$(mise activate zsh)"' >> ~/.zshrcInstall Node.js via mise:
mise use -g nodejs@latestInstall pnpm:
curl -fsSL https://get.pnpm.io/install.sh | sh -Why pnpm over npm?
- Faster installs through content-addressable storage
- Strict dependency isolation prevents phantom dependencies
- Disk space efficient through hard-linking
- More reliable lockfile format
Step 1: Prepare Your Project
Configure Adapter
Install the Cloudflare adapter:
cd frontend
pnpm install -D @sveltejs/adapter-cloudflareUpdate svelte.config.js:
import adapter from '@sveltejs/adapter-cloudflare';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
const config = {
preprocess: vitePreprocess(),
kit: {
adapter: adapter({
// Optional: configure routes
routes: {
include: ['/*'],
exclude: ['<all>']
}
})
}
};
export default config;Environment Variables
Create frontend/.env.production:
PUBLIC_API_URL=https://tcs-svc-9k2m.yourdomain.com
PUBLIC_GRAPHQL_ENDPOINT=https://tcs-svc-9k2m.yourdomain.com/graphql
PUBLIC_APP_URL=https://your-app.pages.devSecurity Note: Use an obscure subdomain like tcs-svc-9k2m instead of predictable names like api or backend. Attackers scan for common subdomains automatically. An unguessable name hides your backend from reconnaissance and reduces automated attacks.
Step 2: Deploy via Web UI
Connect Repository
- Go to dash.cloudflare.com and log in
- Navigate to "Pages" in the left sidebar
- Click "Create a project"
- Connect to Git provider (GitHub or GitLab)
- Select your repository
Configure Build Settings
Cloudflare auto-detects SvelteKit, but verify:
- Framework preset: SvelteKit
- Build command:
pnpm run build - Build output directory:
.svelte-kit/cloudflare - Production branch:
main
If your frontend is in a subdirectory:
- Root directory:
frontend
Click "Save and Deploy"
Wait for Deployment
Cloudflare builds and deploys your site. You'll receive:
- Site URL:
https://your-app.pages.dev - Dashboard URL:
https://dash.cloudflare.com/[account]/pages/view/your-app
Step 3: Environment Variables
Via Web UI
- Go to your Pages project → Settings → Environment variables
- Add variables:
- Key:
PUBLIC_API_URL - Value:
https://tcs-svc-9k2m.yourdomain.com - Environment: Production (and Preview if needed)
- Key:
Via Wrangler CLI
First, install Wrangler:
pnpm add -g wranglerLogin to Cloudflare:
wrangler loginSet environment variables:
wrangler pages project env add PUBLIC_API_URL
# Enter value when promptedStep 4: Custom Domain
Add Domain
- Go to your Pages project → Custom domains
- Click "Set up a custom domain"
- Enter your domain:
yourapp.com - Click "Continue"
Configure DNS
Cloudflare will prompt you to either:
Option A: Use Cloudflare as DNS provider (Recommended)
- Change nameservers at your registrar to Cloudflare's nameservers (provided in setup)
- Cloudflare automatically handles SSL and routing
Option B: Use external DNS
Add a CNAME record:
Type: CNAME
Name: www
Value: your-app.pages.devFor apex domain (yourapp.com), use:
Type: A
Name: @
Value: 192.0.2.1Enable HTTPS
Cloudflare automatically provisions SSL certificates. No manual setup needed.
Step 5: Edge Functions (Optional)
Cloudflare Pages supports edge functions through Cloudflare Workers:
Create frontend/functions/api/hello.ts:
export interface Env {}
export const onRequest: PagesFunction<Env> = async (context) => {
const { request, env } = context;
return new Response(JSON.stringify({
message: "Hello from the edge!",
timestamp: new Date().toISOString()
}), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=60'
}
});
};Edge functions run at Cloudflare's edge locations, close to users.
Advanced Configuration
_headers File
Create frontend/static/_headers for custom headers:
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
/*.js
Cache-Control: public, max-age=31536000, immutable_redirects File
Create frontend/static/_redirects for redirects:
/old-path /new-path 301
/api/* https://tcs-svc-9k2m.yourdomain.com/api/:splat 200wrangler.toml Configuration
Create frontend/wrangler.toml for advanced settings:
name = "your-app"
compatibility_date = "2024-01-01"
[env.production]
vars = { ENVIRONMENT = "production" }
[env.staging]
vars = { ENVIRONMENT = "staging" }Troubleshooting
Build Failures
Check build logs in Cloudflare dashboard. Common issues:
Node version mismatch:
Add to package.json:
{
"engines": {
"node": "20"
}
}Lock file issues:
# Regenerate lock file
rm pnpm-lock.yaml
pnpm install404 on Client-Side Routes
The Cloudflare adapter handles this automatically. If issues persist, check:
svelte.config.jsuses@sveltejs/adapter-cloudflare- Build output directory is
.svelte-kit/cloudflare
Environment Variables Not Working
- Check environment (Production vs Preview)
- Ensure variables start with
PUBLIC_for browser access - Trigger a new deploy after adding variables
- For private variables (server-side only), don't use
PUBLIC_prefix
API Routes Not Working
Verify in svelte.config.js:
adapter: adapter({
routes: {
include: ['/*'],
exclude: ['<all>']
}
})Production Checklist
- Site builds without errors
- Environment variables configured
- Custom domain added (if applicable)
- HTTPS enabled
- API endpoints connect to backend
- Edge functions working (if using)
- Branch deploys tested
- Analytics configured (optional)