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.

Zum Quellcode
Schritt 1 von 4

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.

lunora/schema.ts
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

Schritt 2 von 4

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.

lunora/messages.ts
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

Schritt 3 von 4

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.

src/App.tsx
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

Schritt 4 von 4

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.

Cloudflare

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.

LunoraConvexFirebaseCloudflare pur
Typsicher von Ende zu Endepartialselbst bauen
Realtime-Subscriptionsselbst bauen
Läuft im eigenen Account
Skaliert über ein Durable Object hinausn/an/aselbst bauen
Lokale Entwicklung Vite-firstn/an/aselbst 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-app
cd my-app && pnpm install
pnpm dev
214
Sterne auf GitHub
v1.0.0-alpha
Aktuelle Version
FSL-1.1
Source-available, nach zwei Jahren Apache-2.0

Gemeinsam bauen

Lunora entsteht öffentlich und entwickelt sich schnell. Issues, Fragen und Pull Requests sind willkommen.

Lunora auf GitHub
Anolilab Jungle