GitHubnpm

Deployment

Juice builds to a standard fetch handler. Deploy to Cloudflare Workers, Bun, Deno, or Node.js with a single server.ts file.

Build for Production

The juice build command runs two Vite builds:

  1. Client build — produces client chunks and the flight manifest
  2. SSR build — produces the server bundle (dist/server.js)
juice build

Preview Locally

Run the production build locally to verify everything works before deploying:

juice preview

Cloudflare Workers

// server.ts
import { createRouter } from '@cmj/juice/runtime';
import manifest from './flight-manifest.json';

export default {
  fetch: createRouter(manifest, {
    root: import.meta.url,
  }),
};
# wrangler.toml
name = "my-app"
main = "dist/server.js"
compatibility_date = "2024-01-01"

[site]
bucket = "./dist/client"
wrangler deploy

Bun

// server.ts
import { createRouter } from '@cmj/juice/runtime';
import manifest from './flight-manifest.json';

const handler = createRouter(manifest, {
  root: import.meta.url,
});

Bun.serve({
  port: 3000,
  fetch: handler,
});

console.log('Listening on http://localhost:3000');
bun server.ts

Deno

// server.ts
import { createRouter } from '@cmj/juice/runtime';
import manifest from './flight-manifest.json';

const handler = createRouter(manifest, {
  root: import.meta.url,
});

Deno.serve({ port: 3000 }, handler);
deno run --allow-net --allow-read server.ts

Node.js

// server.ts
import { createServer } from 'node:http';
import { createRouter } from '@cmj/juice/runtime';
import manifest from './flight-manifest.json';

const handler = createRouter(manifest, {
  root: import.meta.url,
});

const server = createServer(async (req, res) => {
  const url = new URL(req.url!, `http://${req.headers.host}`);
  const request = new Request(url, {
    method: req.method,
    headers: req.headers as HeadersInit,
  });

  const response = await handler(request);

  res.writeHead(response.status, Object.fromEntries(response.headers));
  const body = await response.text();
  res.end(body);
});

server.listen(3000, () => {
  console.log('Listening on http://localhost:3000');
});