Skip to content

Repository files navigation

Ramose — reactive applications that grow safely

npm license docs

The typed, realtime database for apps on Cloudflare — describe your data in TypeScript, write it through a typed API, and read it with queries that update themselves in every open tab.

Docs · Getting started · Tour of Reef · Examples


A schema, a live query, and a typed write — that is the whole app:

import * as Ramose from "ramose/db";
import { useLive, useTransact } from "ramose/react";
import * as Schema from "effect/Schema";

const Todo = Ramose.Namespace("todo", {
  title: Ramose.Attr(Schema.String),
  done: Ramose.Attr(Schema.Boolean),
});

const ramose = Ramose.connect({ url: import.meta.env.VITE_RAMOSE_URL });
const db = ramose.db("todos", Ramose.Catalog({ todo: Todo }));

// A query is a value: declare it once, then run it live.
const todos = Ramose.query(Todo).select({ id: Todo.id, title: Todo.title, done: Todo.done });

const Todos = () => {
  const { rows } = useLive(db, todos);   // re-runs itself whenever the data changes
  const { run } = useTransact();

  const toggle = (todo: Ramose.Row<typeof todos>) =>
    run(
      db.transact(function* (tx) {
        yield* tx.add(todo.id, Todo.done, !todo.done);
      }),
    );

  return (
    <ul>
      {rows?.map((todo) => (
        <li key={todo.id} onClick={() => void toggle(todo)}>
          {todo.title}
        </li>
      ))}
    </ul>
  );
};

Nothing refetches after that write, and nothing invalidates a cache: useLive is a query the server keeps up to date, in every tab that is watching it.


  • A typed schema. One TypeScript file your app, your rules, and your deploy all import. A wrong write is a red squiggle, not a bad row.
  • Live queries. useLive(db, query) re-runs itself when the data changes. No refetch code, no invalidation, no WebSocket server to write.
  • Permissions in the database. Who may read or write each field is checked on the server, deny by default — not middleware you remember to add.
  • A database per customer. ramose.db("acme", schema) is a function call, not a provisioning step.
  • Nothing overwritten. Every version is kept; read the database as it was at any earlier point in time.
  • Your Cloudflare account. One Worker, Durable Objects, and R2, deployed with Alchemy. No Ramose bill, no dashboard, no managed service.
bun add ramose react react-dom

One package. effect, alchemy and the two @effect/platform-* packages come with it at versions that resolve, so there is nothing else to pin. React is an optional peer — a server-only app installs ramose alone.

Learn more

Ramose is pre-release. The API moves between releases, so pin exact versions. Issues and pull requests are welcome.

Contributing

Ramose itself is a Bun monorepo — bun install && bun test. See CONTRIBUTING.md.

License

Apache-2.0 — see LICENSE and NOTICE.

About

Ramose — an immutable, reactive database for Cloudflare

Resources

Contributing

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages