Show HN: Oxide – the back end (un)framework that won't get in your way

ryuzyy1 pts1 comments

Oxide - The backend unframeworkSkip to content<br>Search⌘KEsc

↑↓navigate↵open⌘Jpreview

svg]:size-3! inline-flex w-fit shrink-0 items-center justify-center whitespace-nowrap overflow-hidden transition-[color,box-shadow] gap-1 [&>svg]:pointer-events-none bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80 rounded-full text-sm h-6">AlphaThe backend unframework.<br>Ship a backend from the bundler you already use. Call the server from the client like a function.<br>svg]:px-4 has-[.badge:last-child]:pr-3 [&_.badge:last-child]:ml-1.5" href="/getting-started">Get startedsvg]:px-4 has-[.badge:last-child]:pr-3 [&_.badge:last-child]:ml-1.5" href="https://github.com/ryuzcorp/oxide" rel="noreferrer" target="_blank">View on GitHub

img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl border border-border shadow-lg group/card flex flex-col overflow-clip [&:has(>_[data-slot=card-media]:first-child_img)]:pt-0">Four files. That's the whole app.<br>A server, an action, a client, and the plugin.<br>svg]:px-2" target="_blank" rel="noopener noreferrer" href="https://stackblitz.com/github/ryuzcorp/oxide/tree/main/templates/tasks?file=src%2Ftasks.server.ts" type="button">Run

client.tsnotes.server.tsserver.tsvite.config.ts<br>// Looks local. Runs on the server.<br>import { create, list } from "./notes.server";

const note = await create("Ship Oxide");<br>const notes = await list();<br>console.log(note, notes);<br>// { id: "…", title: "Ship Oxide" } [{ id: "1", title: "Ship Oxide" }]

// Talk to a database or any external service here.<br>export async function create(title: string) {<br>return { id: crypto.randomUUID(), title };

export async function list() {<br>return [{ id: "1", title: "Ship Oxide" }];

import { handle } from "tacho/transport/fetch";<br>import { tacho } from "tacho";

const rpc = tacho();

const app = rpc({<br>health: rpc.run(() => "ok" as const),<br>});

export default {<br>fetch: handle(app),<br>};

import { defineConfig } from "vite";<br>import oxide from "oxidejs/vite";

export default defineConfig({<br>plugins: [oxide()],<br>});

It guides you. It doesn't frame you.<br>img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl border border-border shadow-lg group/card flex flex-col overflow-clip [&:has(>_[data-slot=card-media]:first-child_img)]:pt-0">Single bundle<br>One folder to deploy. A server, and a client if you have a page.

img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl border border-border shadow-lg group/card flex flex-col overflow-clip [&:has(>_[data-slot=card-media]:first-child_img)]:pt-0">Server actions<br>Import a server function. Call it like it's local.

img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl border border-border shadow-lg group/card flex flex-col overflow-clip [&:has(>_[data-slot=card-media]:first-child_img)]:pt-0">Your host<br>Same plugin on a VPS or on Cloudflare. You pick the host, not a new stack.

Keep your bundler. Add one plugin.<br>Vite or Rsbuild. Switch the import. Keep the rest.<br>svg]:px-2.5 mt-6 pl-0" href="/oxide/quickstart">Read the quickstart →<br>ViteRsbuild<br>import { defineConfig } from "vite";<br>import oxide from "oxidejs/vite";

export default defineConfig({<br>plugins: [oxide()],<br>});

img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl border border-border shadow-lg group/card flex flex-col overflow-clip [&:has(>_[data-slot=card-media]:first-child_img)]:pt-0">Your backend can start this small.<br>Install Oxide, add the plugin, write an action.

svg]:px-4 has-[.badge:last-child]:pr-3 [&_.badge:last-child]:ml-1.5" href="/getting-started">Get started

child first data border oxide size

Related Articles