The backend unframework.
Ship a backend from the bundler you already use. Call the server from the client like a function.
// notes.server.ts
export async function create(title: string) {
return { id: crypto.randomUUID(), title };
}
// client.ts
import { create } from "./notes.server";
const note = await create("Ship Oxide");Looks local. Runs on the server.
// vite.config.ts
import { defineConfig } from "vite";
import oxide from "oxidejs/vite";
export default defineConfig({
plugins: [oxide()],
});Vite or Rsbuild. Switch the import. Keep the rest.
npm i oxidejs tachoIt guides you. It doesn't frame you.
- Single bundle — One folder to deploy. A server, and a client if you have a page.
- Server actions — Import a server function. Call it like it's local.
- Your host — Same plugin on a VPS or on Cloudflare. You pick the host, not a new stack.
| Package | Purpose |
|---|---|
| oxidejs | Turns Vite or Rsbuild into a backend. One plugin, one folder to deploy. |
| tacho | Typed JSON-RPC. The wire those actions ride on. Also usable on its own. |
Need RPC without the plugin? Use tacho. typeof router is the client.
MIT © Ryuz