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

PlatformRuntimeTypical setup
Static CDN—mode: 'static' or hybrid pre-render → upload dist/
Node.js 18+Nodeemberkit serve after emberkit build
Cloudflare WorkersV8 isolates@emberkit/edge adapter + Wrangler
Deno DeployDeno@emberkit/edge Deno adapter
BunBunRun 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 typeConfigHost
Marketing / docsstatic or hybridNetlify, Cloudflare Pages, S3
Mixed static + dynamichybridCDN for static + Node/Worker for SSR
Authenticated appspa or ssrAny 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-bind and minimal JS on content pages

Next Steps