@sveltext/adapter-cloudflare-platform
v0.1.0
Published
SvelteKit adapter for Cloudflare Platform: cron, queues, bindings, wrangler validation, and typegen.
Maintainers
Readme
@sveltext/adapter-cloudflare-platform
SvelteKit adapter focused on Cloudflare Workers deployments. It mirrors the official @sveltejs/adapter-cloudflare ergonomics, adds first-class support for Cloudflare cron/queue jobs, and generates Wrangler-aware typings so you can adopt Workers without glue code.
Paired runtime – install and use
@sveltext/cloudflare-platform-runtimein your app to declare cron and queue jobs with a remote-functions style API.
Table of contents
- Why another adapter?
- Installation
- Quick start
- Configuration reference
- Guided migration from
@sveltejs/adapter-cloudflare - Cron & queue workflow
- Manual triggers
- Wrangler validation & hints
- Environment typing
- Developer experience
- CLI utilities
- FAQ
Why another adapter?
- Workers-only focus – assumes you target Workers (not Pages) so the generated worker, validation, and messages can rely on Workers features and nudge you toward best practices.
- Jobs-first ergonomics – remote-style cron/queue helpers ship in the runtime, and the adapter serialises job metadata into the worker bundle so cron/queue registration has zero runtime overhead.
- Wrangler-aware typing – the adapter reads your
wrangler.tomlduring build and generates.svelte-kit/types/cf-platform.d.tswith bindings (kv_namespaces, queues, services, workflows, Hyperdrive, Browser Rendering, etc.). - Actionable validation – missing queue producers, cron schedules, or workflow compatibility dates surface as build errors with copy/paste TOML snippets.
Installation
pnpm add -D @sveltext/adapter-cloudflare-platform @sveltext/cloudflare-platform-runtime
# or: npm install --save-dev …In your svelte.config.js:
import cloudflarePlatform from '@sveltext/adapter-cloudflare-platform';
export default {
kit: {
adapter: cloudflarePlatform({
config: 'wrangler.toml', // optional – autodetected by default
fallback: 'plaintext', // or 'spa'
manual: { base: '/__jobs', enabled: false },
validate: { wrangler: 'error' } // 'warn' | 'off'
})
}
};Ensure wrangler.toml targets Workers (not Pages):
main = "./.cloudflare/_worker.js"
assets = { directory = ".cloudflare", binding = "ASSETS", not_found_handling = "single-page-application" }
compatibility_date = "2024-10-22" # or newer, required for Workflows supportQuick start
Declare jobs
// src/routes/+page.server.ts import { cron, queue } from '@sveltext/cloudflare-platform-runtime'; export const nightly = cron({ schedule: '0 4 * * *' }, async ({ log }) => { log.info('Nightly job'); }); export const emails = queue( { binding: 'MAILS', consume: true, deadLetter: 'MAILS_DLQ' }, async (message) => { await sendEmail(message.body); } );Describe bindings
[[queues.producers]] binding = "MAILS" queue = "project-mails" [[queues.consumers]] queue = "project-mails" dead_letter_queue = "project-mails-dlq" [[queues.producers]] binding = "MAILS_DLQ" queue = "project-mails-dlq"Build
pnpm run build- Generates
.cloudflare/_worker.jsand static assets. - Serialises your job metadata into the worker file (no manifest scanning at runtime).
- Creates
.svelte-kit/types/cf-platform.d.tswith typed bindings + warnings if wrangler config is incomplete.
- Generates
Deploy
pnpm exec wrangler deploy
Configuration reference
| Option | Type / Default | Description |
| ------------- | ------------------------------------------ | ----------- |
| config | string? | Path to wrangler.toml/JSON. Auto-detected if omitted. |
| assetsOut | string (default: '.cloudflare') | Output folder for static assets when assets.directory isn’t set. |
| fallback | 'plaintext' | 'spa' (default: 'plaintext') | Whether to generate an SPA fallback. When 'spa', index.html is created regardless of Wrangler config (you’ll see a warning if not_found_handling isn’t "single-page-application"). |
| manual | { base?: string \| null; enabled?: boolean; headers?: Record<string,string> } | Configure manual cron triggers. base = null disables HTTP endpoints entirely. |
| validate | { wrangler?: 'error' | 'warn' | 'off' } (default: 'error') | Severity for Wrangler validation. |
| platformProxy | Parameters<typeof wrangler.getPlatformProxy>[0] | Forwarded to Wrangler for local emulation. |
Migration guide
Coming from @sveltejs/adapter-cloudflare:
| Area | What changed | How to adapt |
| ---- | ------------ | ------------ |
| Workers vs Pages | This adapter targets Workers only. | Remove Pages-specific config (pages_build_output_dir, site). Keep assets.directory + main. |
| Cron/queue jobs | Jobs live in .remote.ts (or other server modules) using runtime helpers. | Replace manual export const onCron / queue handlers with cron() / queue() helpers. |
| Manual triggers | Automatic HTTP endpoints available at /__jobs/cron/:name. | Configure manual.base / enabled / headers. |
| Typings | Adapter generates .svelte-kit/types/cf-platform.d.ts automatically; optional CLI mirrors Wrangler’s types. | Remove old wrangler types outputs from your repo, or keep them if needed—our generated file lives under .svelte-kit/. |
| Validation | Missing queue producers, cron schedules, workflow compatibility, SPA fallback etc. throw early. | Update wrangler.toml according to hints (copy & paste the suggested TOML slices). |
| Worker boot | Job inventory is embedded; there’s no runtime manifest walk. | No changes needed—just enjoy faster cold starts. |
Cron & queue workflow
- Declare jobs with the runtime helper (any
.server.ts,.remote.ts, or server module). - Build: the adapter scans the generated SvelteKit manifest, collects job metadata, and serialises it into
files/worker.js. - Runtime: the worker lazily
import()s only the modules needed for cron/queue execution, so cold starts stay lean. - Manual triggers: available at
/<manual.base>/cron/:route, respecting global + per-job headers. - Queue producers get stubbed during local dev if bindings are missing, with
console.infologs so you see payloads.
Example manual trigger for local testing:
curl -X POST "http://127.0.0.1:8787/__jobs/cron/nightly" \
-H "x-secret: dev-token"Manual triggers
Configure
manualin the adapter options:manual: { base: '/__jobs', enabled: process.env.NODE_ENV !== 'production', headers: { 'x-secret': process.env.JOBS_SECRET ?? '' } }For each
cron()job withmanual: trueor an explicitmanual.route, the worker exposes/{base}/cron/{route}.Required headers merge in the following order (lowest precedence first):
- Adapter-level
manual.headers - Deprecated
cron({ manualHeaders }) - Per-job
cron({ manual: { headers } })
- Adapter-level
If manual triggers are disabled (base: null or enabled: false), endpoints return 404.
Wrangler validation & hints
- Cron schedules – cross-checked with
triggers.crons[]. Missing schedules produce an error with the JSON snippet you can paste. - Queue producers/consumers – validates
queues.producersbindings, queue names, anddead_letter_queue. Missing items return a nicely formatted TOML block. - Workflows – warns if
compatibility_dateis older than2024-10-22. - Remote-only bindings – surfaces a warning telling you to run
wrangler dev --remote(for mTLS certificates, Vectorize, Browser Rendering, Hyperdrive, AI). - Legacy exports – if any job still exports raw
cron/queuehandlers (without runtime metadata), the build fails with a clear migration message.
You can demote validation with validate: { wrangler: 'warn' }, but errors ensure you don’t ship a broken worker.
Environment typing
During adapt we read wrangler.toml and generate .svelte-kit/types/cf-platform.d.ts with entries such as:
declare global {
namespace App {
interface Platform {
env: {
ASSETS: Fetcher;
DB: D1Database;
MAILS: Queue;
MAILS_DLQ: Queue;
MAIL_SERVICE: Fetcher;
WORKFLOW: Workflow;
VECTOR: VectorizeIndex;
// …
[key: string]: unknown;
};
}
}
}We import both @cloudflare/workers-types and @cloudflare/workers-types/experimental, so bleeding-edge bindings resolve without manual augmentation.
Need standalone typings? Use the CLI below or run
wrangler types --experimental-typings. Either way, keep.svelte-kit/types/out of version control.
Developer experience
adapter.emulate()
When using Vite preview or the SvelteKit dev server:
const adapter = cloudflarePlatform();
const { platform, jobs } = adapter.emulate();
const { env } = await platform();
jobs.log(); // pretty-prints cron + queue definitions
jobs.definitions() // returns JSON metadataLocal queues / cron
queue()producers stubenv[binding].send()if the binding doesn’t exist during dev, logging payloads so you can verify messages.- Cron jobs are invokable via the manual HTTP endpoints described earlier.
Remote development hints
Bindings that Cloudflare can’t simulate locally (mTLS certs, Hyperdrive, Vectorize, Browser Rendering, Workers AI) trigger a warning suggesting wrangler dev --remote / --remote-binds.
CLI utilities
The packaged binary mirrors Wrangler’s output but stays inside your project:
pnpm exec sveltext-cf-typegen --config wrangler.tomlOutputs .svelte-kit/types/cf-platform.d.ts using the same generator the adapter calls during adapt. Useful when you want the types without a full SvelteKit build.
CLI flags:
| Flag | Description |
| ----------- | ---------------------------------------- |
| --config | Path to wrangler.toml / JSON. |
FAQ
Do I need to check in .cloudflare assets?
No. Treat the build output the same way you do with other SvelteKit adapters: run pnpm build, then let Wrangler deploy from .cloudflare/. Ignore the directory in git if you prefer.
How do I deploy to Cloudflare Pages?
The adapter assumes Workers deployments. For Pages, stick with @sveltejs/adapter-cloudflare – it handles _routes.json, assets routing, and other Pages specifics.
Can I combine this with other adapters?
Not directly. SvelteKit loads exactly one adapter per configuration file. If you deploy to multiple platforms, manage separate svelte.config.* files or use project-specific scripts.
Questions or feedback? Open an issue or start a discussion – we want to make Cloudflare Workers feel completely native in SvelteKit.
