Skip to content
rodolfo.gg
Go back

How to deploy a Svelte+SvelteKit application on Cloudflare Workers (free).

CC BY-NC-ND 4.0
Rodolfo González González

How to deploy a Svelte+SvelteKit application on Cloudflare Workers (free).

Introduction

According to Wikipedia:

Cloudflare, Inc. is an American company that provides a content delivery network, Internet security services, and distributed domain name server services, sitting between the visitor and the Cloudflare user’s hosting provider, acting as a reverse proxy for websites.

Workers is based on a lightweight execution engine built on Node.js (not Node.js directly). It is much faster and more practical than using a FaaS on Aliyun FC or Amazon Lambda to deploy applications like this blog built with Astro, although each technology has its own advantages and disadvantages. One advantage of Workers is the speed of its execution. Another is its cost.

This guide shows how to deploy a Svelte+SvelteKit application on Cloudflare Workers (free).

1) What to do in Cloudflare (dashboard)

  1. Create/use a Cloudflare account (Free plan).
  2. Go to Develop -> Workers & Pages and enable Workers on the account.
  3. (Recommended) Create an API Token for deploy from CLI:
  4. Go to Manage account -> Account API Tokens.
  5. Under Account Resources: select your account.
  6. Create token
  7. Use the Edit Cloudflare Workers template (it has the minimum required permissions)
  8. If using a custom domain:
  1. Select the Zone Resources according to the zones the token will cover.
  2. Click Continue to summary → Create Token.
  1. If using a custom domain:

    • Have the zone (yourdomain.com) in Cloudflare.
    • On the deployed Worker: Settings -> Domains & Routes -> Add Custom Domain
  2. The new token can be tested:

Terminal window
curl "https://api.cloudflare.com/client/v4/accounts/xxx123/tokens/verify" \
-H "Authorization: Bearer cfat_ABCD_my_token"

2) What to configure in the project

The project must be aligned to a pure Worker:

wrangler.toml
- `main = "build/_worker.js"`
- `[assets] directory = "build", binding = "ASSETS"`

If you don’t have the account_id, add it:

wrangler.toml
account_id = "your_account_id"

The account_id can be found in the Cloudflare dashboard, in the right sidebar of your domain, or with:

bunx wrangler whoami

It is, of course, very important to use the adapter-cloudflare:

svelte.config.js
import adapter from '@sveltejs/adapter-cloudflare';

Local requirements

  1. Dependencies:
  1. Configure the token in your local environment
Terminal window
export CLOUDFLARE_API_TOKEN=cfat_ABCD_my_token

Or permanently in ~/.bashrc, ~/.zshrc or the appropriate file for your shell:

Terminal window
echo 'export CLOUDFLARE_API_TOKEN=your_token_here' >> ~/.bashrc

Alternatively with wrangler:

Terminal window
bunx wrangler login

This opens a browser for OAuth. Personally, I don’t like it.

If you prefer a direct token:

Terminal window
bunx wrangler config

3) Variables and secrets (important)

In your current app

If import.meta.env.VITE_* (build-time) is used, that means:

Critical examples could be:

Runtime secrets (optional)

If you later want to add secrets at runtime:

Terminal window
bunx wrangler secret put VARIABLE_NAME

and read them from env.VARIABLE_NAME.

4) Build + deploy (step by step)

In the following steps you can replace npm with bun in the commands:

  1. Install dependencies:
Terminal window
npm ci
  1. Configure token:
Terminal window
export CLOUDFLARE_API_TOKEN=your_token
  1. Prepare the build .env (with your correct VITE_* values).

  2. Build:

Terminal window
make build
# npm run build
# bun run build
  1. Verify output:
  1. Test the Worker locally:
Terminal window
make preview
# bunx wrangler dev
  1. Deploy:
Terminal window
make deploy
# bunx wrangler deploy
  1. Test the Worker, which will be available at:

https://example-frontend.your-subdomain.workers.dev

or at your custom domain if configured in the dashboard.

5) OIDC configuration (Zitadel or another provider) for production

If using an OIDC provider such as Zitadel, you must register the required endpoints with the provider:

  1. Redirect URI(s) (login callback).
  2. Post-logout redirect URI(s).
  3. Web origins of the frontend.

6) Post-deploy checks

To view logs:

Terminal window
npx wrangler tail

7) Free Workers limits to consider (reviewed on April 7, 2026)

If you exceed these limits, you will get 1027/quota errors.

8) Typical errors

  1. Cannot read properties of undefined (reading 'fetch')
  1. Empty VITE_* variables in production
  1. Zitadel login fails in prod

9) Deploy on custom domain

There are 2 ways to do this, assuming the domain is in Cloudflare:

A. Using wrangler.toml

Configure the routes:

routes = [
{ pattern = "www.example.com/*", zone_name = "example.com" }
]

Then do the normal deploy:

Terminal window
bunx wrangler deploy

B. In the Cloudflare dashboard

  1. Go to Workers & Pages → your worker → Settings → Triggers
  2. Click Add Custom Domain
  3. Type www.example.com
  4. Cloudflare automatically creates the DNS record and TLS certificate

Domain outside Cloudflare

If the domain is not in Cloudflare:

You must first add the domain to Cloudflare (or at least use an external DNS record):

In your registrar’s DNS, create a CNAME record:

In tinydns, for example:

Terminal window
Cwww:your-project.your-subdomain.workers.dev:86400

Then in Cloudflare, go to the worker and in Triggers click Add Custom Domain and add www.example.com.

Difference between routes and custom_domain

Featureroutescustom_domain
Requires zone in CFYesYes
Configurable in tomlYesYes
Automatic TLSManual (already existing)Automatic
Shared with other workersYes (by pattern)No

For a subdomain dedicated to the worker, custom_domain is the cleanest option:

wrangler.toml
routes = [
{ pattern = "ssr.example.com/*", custom_domain = true, zone_name = "example.com" }
]

Or the alternative syntax:

[[env.production.routes]]
pattern = "ssr.example.com/*"
zone_name = "example.com"

Bonus: Useful Makefile rules

deploy:
bunx wrangler deploy
preview:
bunx wrangler dev
build:
@echo "Building with $(DOTENV_FILE)"
DOTENV_FILE=$(DOTENV_FILE) bun run build

Official sources used


Share this post on:

Previous Post
How to install caveman in Visual Studio Code for Claude Code.
Next Post
How to Get Authorization Tokens on HuggingFace.