JSPM

  • Created
  • Published
  • Downloads 63
  • Score
    100M100P100Q70718F
  • License MIT

Zero-bloat React 19 RSC framework — streaming SSR, server actions, zero config.

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@^6

Quickstart

npx @cmj/create-juice-app my-app
cd my-app
npm install
npm run dev

Or scaffold for a specific target:

npx @cmj/create-juice-app my-app --target cloudflare

Targets: 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
  1. Compile: The Vite plugin detects 'use client' and 'use server' directives, generates proxy modules, and emits a flight-manifest.json.
  2. Serve: The runtime reads the manifest and streams RSC responses using React 19's renderToReadableStream.
  3. Deploy: The Request → Response signature works on any WinterCG platform.

Client-Side Navigation

import { Link } from '@cmj/juice/client';

<Link href="/about">About</Link>
<Link href="/products" prefetch="viewport">Products</Link>
<Link href="/blog" activeClassName="active">Blog</Link>

Programmatic navigation:

'use client';
import { useRouter } from '@cmj/juice/client';

const router = useRouter();
router.push('/dashboard');
router.prefetch('/settings');

In dev mode, the Vite plugin auto-injects a client bootstrap that intercepts navigations via the Navigation API — SPA transitions with View Transitions, zero config.

CSS & Styling

Import .css files from any component — they're collected and injected as <link> tags automatically.

// app/routes/layout.tsx
import './global.css';

CSS modules work out of the box:

import styles from './Button.module.css';
<button className={styles.root}>Click</button>
Environment Mechanism
Dev Vite module graph walked recursively — <link> tags in <head>
Production CSS assets tracked in flight-manifest.json under the css key

PostCSS, Sass, Less, Stylus — anything Vite supports works automatically.

Features

  • React 19 RSC — Server Components, Suspense, streaming SSR
  • Server Actions'use server' with FormData + opt-in ActionContext for headers, cookies, params
  • SPA navigation<Link> component + useRouter() hook + Navigation API bootstrap in dev
  • CSS pipelineimport './styles.css', CSS modules, PostCSS, Sass — dev and production
  • Zero config — One plugin call, no magic files
  • One dependency — Only urlpattern-polyfill for 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 createActionContext factory for unit testing

License

MIT