Overview
One Vite or Rsbuild plugin. One build. A server bundle — and a client only if you ship a page.
Oxide is the backend unframework. You keep Vite or Rsbuild. The plugin emits a deployable tree: dist/server.js, plus dist/client/ when you have index.html. Server actions are Effect RPC with the same TypeScript types on both sides. The function body never enters the client bundle.
When to use it
Use Oxide when you want a small typed full-stack app: a server entry, optional static UI, and *.server.ts actions. Stay on a full framework if you need file-based routing, a component SSR model, or a large app shell.
- Use Oxide for one plugin, one output tree, and typed RPC without a second API layer.
- Use a framework when you need more than a server entry and actions.
What you get
- One output tree —
dist/server.js, and a client only when you have a page (Node). Workers apps use@cloudflare/vite-pluginfor the build layout. - Server actions —
export const x = action(...)in*.server.ts. Importxfrom the browser; Oxide swaps in an Effect RPC stub. Types stay shared. Secrets and helpers that are not wrapped inaction()never cross the wire. See Server actions. - Streams and live data —
async function*over newline-delimited JSON-RPC;liveQueryfor topic snapshots on WebSocket. - Node or Cloudflare — default Node when no wrangler file.
presetis"worker"whenwrangler.jsonc/.toml/.jsonis present (or set it yourself). - Workflows, queues, schedules — Cloudflare / celld durable work from
*.server.ts. See Worker. - Vite and Rsbuild — same options, same Node layout.
You can ship a server-only worker (no index.html) or a UI that calls actions with no hand-written /api routes. Worker production builds also prepare a celld-ready dist/wrangler.json when Cloudflare Vite leaves an SSR snapshot.
What it does not do
- No oxide-owned workerd emulation (use
@cloudflare/vite-plugin) - No automatic
celld deploy/wrangler deploy(prepare only) - No Node-builtin polyfills — a stray Node import fails the build