GitHubnpm

Quickstart

Create a new Juice app, pick your deploy target, and start the dev server in under a minute.

Install

npx @cmj/juice create my-app

The CLI walks you through target selection. You can also pass it directly:

npx @cmj/juice create my-app --target bun
npx @cmj/juice create my-app --target node
npx @cmj/juice create my-app --target cloudflare
npx @cmj/juice create my-app --target deno

Project Structure

The scaffolder creates 13 files (14 for Cloudflare, which adds wrangler.toml):

my-app/
  package.json
  tsconfig.json
  vite.config.ts
  flight-manifest.json
  .gitignore
  server.ts
  app/
    routes/
      layout.tsx          # Root layout (html, head, body)
      global.css          # Global styles
      home.tsx            # Index route (/)
      middleware.ts        # Root middleware
      product/[id].tsx    # Dynamic route (/product/:id)
      api/health.ts       # API route (/api/health)
    components/
      counter.tsx         # Client component ('use client')

Run the Dev Server

cd my-app
bun install
bun run dev

This starts Vite with the Juice plugin. Hot module replacement works out of the box for both server and client components.

What Each File Does

FilePurpose
server.tsProduction entry point. Imports the manifest and calls createRouter().
vite.config.tsVite config with the Juice plugin. One line: plugins: [juice()].
flight-manifest.jsonBridge between compiler and runtime. Auto-generated on build.
layout.tsxRoot layout wrapping every page. Renders <html>, <head>, <body>.
home.tsxThe index route. Default export is a React Server Component.
middleware.tsRoot middleware. Runs before every route. Receives (req, next).
product/[id].tsxDynamic route with typed params via PageProps.
api/health.tsAPI route exporting a GET handler. Returns JSON, no React.
counter.tsxClient component with 'use client' directive. Interactive on the browser.

Build for Production

bun run build    # Client + SSR bundle
bun run preview  # Run the production build locally