Edge Deployment
Deploy EmberKit apps to edge runtimes or traditional Node servers. Pre-rendered static output works on any CDN; dynamic routes use the SSR bundle from dist/server/entry-server.js.
Supported Platforms
| Platform | Runtime | Typical setup |
|---|---|---|
| Static CDN | — | mode: 'static' or hybrid pre-render → upload dist/ |
| Node.js 18+ | Node | emberkit serve after emberkit build |
| Cloudflare Workers | V8 isolates | @emberkit/edge adapter + Wrangler |
| Deno Deploy | Deno | @emberkit/edge Deno adapter |
| Bun | Bun | Run SSR entry or static dist/ |
Node production server
After building with ssr or hybrid mode:
pnpm build
pnpm exec emberkit serve
serve reads dist/ssr-manifest.json, serves pre-rendered HTML, and falls back to dist/server/entry-server.js for dynamic routes.
For a lighter local check:
pnpm preview # emberkit preview
Cloudflare Workers
pnpm add -D wrangler @cloudflare/workers-types @emberkit/edge
// wrangler.jsonc — production pattern (Orange Ember website)
{
"name": "my-app",
"main": "worker.ts",
"compatibility_date": "2026-04-03",
"compatibility_flags": ["global_fetch_strictly_public", "nodejs_compat"],
"assets": {
"directory": "./dist",
"binding": "ASSETS",
"not_found_handling": "single-page-application"
},
"observability": { "enabled": true }
}
Or build the same defaults in TypeScript:
import { defineWranglerConfig } from '@emberkit/edge';
export default defineWranglerConfig({
name: 'my-app',
main: 'worker.ts',
});
Worker entry (shared API + static dist/):
import { createCloudflareWorker } from '@emberkit/edge';
import { handleApiRequest } from './src/server/api-router';
export default createCloudflareWorker({
handleApi: handleApiRequest,
injectPublicEnv: true, // exposes PUBLIC_* on window.__CF_ENV__
});
Scripts: pnpm build && wrangler deploy, pnpm build && wrangler dev for preview, wrangler types for Env bindings.
Use sqlRawPlugin / bare import sql from './schema.sql' (via emberkitVitePlugin) so SQL migrations bundle without a filesystem at runtime.
Deno Deploy
Use @emberkit/edge Deno adapter with a built dist/ output, or serve pre-rendered static files only:
deployctl deploy --project=my-app ./dist
Bundle size helpers
@emberkit/edge includes utilities for edge bundle checks:
import { analyzeBundle, minifyHTML, StaticPage } from '@emberkit/edge';
const stats = analyzeBundle(workerCode);
// stats.size, stats.warnings, stats.errors (8KB hard limit constant)
const html = minifyHTML('<div> <p> Hello </p> </div>');
const page = new StaticPage('<html>...</html>');
page.addStyle('/styles/main.css');
page.addScript('/app.js');
const output = page.toHTML();
Constants: EDGE_BUNDLE_SIZE_WARNING (1KB), MAX_BUNDLE_SIZE (8KB).
Deployment patterns
| App type | Config | Host |
|---|---|---|
| Marketing / docs | static or hybrid | Netlify, Cloudflare Pages, S3 |
| Mixed static + dynamic | hybrid | CDN for static + Node/Worker for SSR |
| Authenticated app | spa or ssr | Any static host + API |
Performance goals
Speed is EmberKit’s first principle. Edge-friendly deployments combine:
- Pre-rendered HTML for static routes — low TTFB and fast First Contentful Paint at the CDN
- SSR at the edge only where routes need per-request data
- Selective hydration — small client bundles via
data-ek-bindand minimal JS on content pages
Next Steps
- SSR & SSG — Rendering modes and build output
- Hydration — Client bindings
- SEO & Meta — Meta tags and JSON-LD