Install.
Requires Bun ≥ 1.3 and the Elm compiler. Wrangler is only needed if you target Cloudflare Workers.
bun add elm-ssr
elm-ssr is one package. It ships the CLI, a Fetch-compatible SSR runtime, the Elm authoring modules, and a SQL migration runner. It runs wherever you can call a standard Request → Response handler.
Requires Bun ≥ 1.3 and the Elm compiler. Wrangler is only needed if you target Cloudflare Workers.
bun add elm-ssr
Run elm-ssr init in an empty directory. It generates elm-ssr.config.json, runtime.ts, worker.ts, starter routes, and an island.
mkdir my-app && cd my-app
bun add elm-ssr
bunx elm-ssr init my-app
bunx elm-ssr init my-app --db
bunx elm-ssr init my-app --auth betterAuth
Use elm-ssr new to add an app to a workspace that already has elm-ssr.config.json. Use --in apps to group under a subdirectory.
bunx elm-ssr new my-app
bunx elm-ssr new my-app --in apps
bunx elm-ssr new my-app --db --auth betterAuth
Routes live in src/<Namespace>/Routes/, islands in Islands/. The CLI scans both on build. Generated output goes to generated/ and is gitignored.
elm-ssr.config.json
package.json
my-app/
elm.json
runtime.ts # createWorkerApp(...)
worker.ts # export default worker
src/MyApp/
Routes/
Index.elm
Counter.elm
NotFound.elm
Islands/
Counter.elm
View/
Shared.elm
migrations/ # optional, with --db
generated/ # build output (gitignored)
The build command scans your routes and islands, generates the Elm router and island manifest, syncs the authoring modules, then runs elm make. Run it every time you add or rename a route or island.
bunx elm-ssr build
Runs build then wrangler dev. Gives you a local Cloudflare Workers environment with D1, KV, and Queues bindings.
bunx elm-ssr dev
The generated runtime exports a standard worker.fetch handler. Wire it directly into any Fetch-compatible runtime.
import { worker } from "./my-app/runtime";
Bun.serve({
port: 3000,
fetch: (req) => worker.fetch(req, process.env)
});
Provider-specific code stays in runtime.ts. The Elm routes and islands are untouched. For Cloudflare Workers, compress before deploying to serve pre-gzipped bundles.
bunx elm-ssr compress
wrangler deploy