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-appThe 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 denoProject 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 devThis starts Vite with the Juice plugin. Hot module replacement works out of the box for both server and client components.
What Each File Does
| File | Purpose |
|---|---|
server.ts | Production entry point. Imports the manifest and calls createRouter(). |
vite.config.ts | Vite config with the Juice plugin. One line: plugins: [juice()]. |
flight-manifest.json | Bridge between compiler and runtime. Auto-generated on build. |
layout.tsx | Root layout wrapping every page. Renders <html>, <head>, <body>. |
home.tsx | The index route. Default export is a React Server Component. |
middleware.ts | Root middleware. Runs before every route. Receives (req, next). |
product/[id].tsx | Dynamic route with typed params via PageProps. |
api/health.ts | API route exporting a GET handler. Returns JSON, no React. |
counter.tsx | Client 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 locallyNext
Core Concepts