Lunora Backend-Framework
Ein typsicheres Realtime-Backend im eigenen Cloudflare-Account.
Vier Dateien und rund vierzig Zeilen. Der Reihe nach gelesen ist das bereits das ganze Modell, denn viel mehr gibt es nicht.
Die Daten einmal beschreiben.
Das Schema ist die Quelle der Wahrheit für Datenbank, Server-Funktionen und Client-Typen. Es gibt keine zweite Definition, die nachgezogen werden muss.
import { defineSchema, defineTable, v } from "@lunora/server";
export default defineSchema({
messages: defineTable({
author: v.string(),
body: v.string(),
ts: v.number(),
}),
});Weiter: ganz normale Funktionen dagegen schreiben
Ganz normale Funktionen dagegen schreiben.
Eine Query liest, eine Mutation schreibt, und beide sind ganz normales TypeScript mit typisiertem Kontext. Keine Controller, keine Routing-Tabelle, keine Serialisierung von Hand.
import { mutation, query, v } from "./_generated/server";
export const list = query.query(async ({ ctx }) =>
ctx.db.query("messages").order("desc").take(50));
export const send = mutation
.input({ author: v.string(), body: v.string() })
.mutation(async ({ ctx, args }) => {
await ctx.db.insert("messages", { ...args, ts: Date.now() });
});Weiter: vom Client lesen
Die Liste bleibt live.
Queries sind Subscriptions. Die Komponente rendert neu, sobald sich die Daten dahinter ändern, auf jedem verbundenen Client, ohne Socket-Verdrahtung und ohne Cache-Invalidierung.
import { useQuery, useMutation } from "@lunora/react";
import { api } from "../lunora/_generated/api";
const messages = useQuery(api.messages.list) ?? [];
const send = useMutation(api.messages.send);Zuletzt: wo das alles läuft
Es bleibt Ihr Account.
Managed Backends verlangen, die Daten auf ihre Server zu verschieben, und rechnen später ab. Lunora deployt dieselben Primitives in den Cloudflare-Account, der Ihnen ohnehin gehört: Projekte im Leerlauf kosten praktisch nichts, und ein Wechsel kostet ein Redeploy.
Workers
Ihre Funktionen laufen als Workers, lokal in derselben Runtime wie in der Produktion.
Durable Objects
SQLite-gestützter State an der Edge. Nach Tenant-Key shardbar oder Lesezugriffe global repliziert.
D1
Relationaler Speicher für alles, was ein einzelnes Objekt überdauert.
R2
Datei- und Blob-Speicher ohne Egress-Gebühren.
Queues
Hintergrundaufgaben und geplante Jobs, ohne zweiten Anbieter.
Wo es einzuordnen ist
Der Kompromiss, auf dem Lunora aufbaut: die Developer Experience eines Managed Backends, auf Infrastruktur, die Sie kontrollieren.
| Lunora | Convex | Firebase | Cloudflare pur | |
|---|---|---|---|---|
| Typsicher von Ende zu Ende | partial | selbst bauen | ||
| Realtime-Subscriptions | selbst bauen | |||
| Läuft im eigenen Account | ||||
| Skaliert über ein Durable Object hinaus | n/a | n/a | selbst bauen | |
| Lokale Entwicklung Vite-first | n/a | n/a | selbst bauen |
Im Free Tier starten.
Der Starter richtet Schema, Dev-Server auf workerd und einen React-Client ein. Lunora ist Alpha-Software: aus dem Alpha-Tag installieren und damit rechnen, dass sich die API noch ändert.
pnpm dlx lunorash@alpha init my-appcd my-app && pnpm installpnpm devGemeinsam bauen
Lunora entsteht öffentlich und entwickelt sich schnell. Issues, Fragen und Pull Requests sind willkommen.
