Package Exports
- @cmj/juice/client
- @cmj/juice/create
- @cmj/juice/package.json
- @cmj/juice/plugin
- @cmj/juice/runtime
Readme
🧃 Juice
Zero-bloat React 19 RSC framework.
Streaming SSR. Server Actions. Zero config.
Install
npm install @cmj/juice react@^19 react-dom@^19 vite@^6Quickstart
npx @cmj/create-juice-app my-app
cd my-app
npm install
npm run devOr scaffold for a specific target:
npx @cmj/create-juice-app my-app --target cloudflareTargets: bun (default), node, cloudflare, deno
CLI
| Command | Description |
|---|---|
juice create <name> |
Scaffold a new Juice app |
juice dev |
Start the Vite dev server |
juice build |
Production build (client + SSR) |
API
juice/plugin
The Vite plugin. Zero config.
// vite.config.ts
import { defineConfig } from 'vite';
import juice from '@cmj/juice/plugin';
export default defineConfig({
plugins: [juice()],
});juice/runtime
The WinterCG-compliant edge runtime.
// server.ts
import { createRouter } from '@cmj/juice/runtime';
import manifest from './dist/flight-manifest.json' with { type: 'json' };
const handler = createRouter(manifest);
// handler: (Request) => Promise<Response>Server Actions (Two-Argument Pattern)
Simple form actions receive FormData as the first argument — React 19 native. When you need more power, use ActionContext as the opt-in second argument:
'use server';
import type { ActionContext } from '@cmj/juice/runtime';
// Simple: FormData-only (React 19 native)
export async function addToCart(formData: FormData) {
const id = formData.get('productId');
}
// Power: headers, cookies, params via second arg
export async function processWebhook(body: unknown, ctx: ActionContext) {
ctx.request.headers.get('x-signature');
ctx.cookies.get('session_id');
ctx.params.id;
}Test your actions with the public createActionContext factory:
import { createActionContext } from '@cmj/juice/runtime';
const ctx = createActionContext(new Request('https://example.com'));How It Works
Source (.tsx) → Vite Plugin → flight-manifest.json → Runtime → Response- Compile: The Vite plugin detects
'use client'and'use server'directives, generates proxy modules, and emits aflight-manifest.json. - Serve: The runtime reads the manifest and streams RSC responses using React 19's
renderToReadableStream. - Deploy: The
Request → Responsesignature works on any WinterCG platform.
Features
- React 19 RSC — Server Components, Suspense, streaming SSR
- Server Actions —
'use server'with FormData + opt-inActionContextfor headers, cookies, params - Zero config — One plugin call, no magic files
- One dependency — Only
urlpattern-polyfillfor cross-platform routing - Multi-platform — Bun, Node.js, Cloudflare Workers, Deno
- Empathic errors — "What-Why-How" error messages for fast debugging
- HMR — Full hot module replacement in development
- Testable actions — Public
createActionContextfactory for unit testing
License
MIT