A type-safe, realtime collaborative Graph Database in a CRDT

@codemix/graph is a groundbreaking graph database solution that combines TypeScript's type safety with Yjs CRDT's conflict-free synchronization. It supports both Gremlin-style and Cypher queries, optimized for real-time collaborative applications and AI integration.
Plane route demo
Global airline routes demo
Load a snapshot of real airline routes into the graph and query it with TypeScript.
Live demo
Add your face to the wall
Powered by @codemix/graph and @codemix/y-graph-storage – a real graph database, synced via a Yjs CRDT across every open tab. Add yourself, rearrange people, draw connections.
Installation
Install the package from npm – no native dependencies, runs anywhere Node or a bundler can.
$ pnpm add @codemix/graph
Note: This is alpha-quality software. We use it in production at codemix and it works well for our use cases, but please be careful using it with your own data.
Define your schema
Describe vertices, edges, and indexes in a plain object. Property types flow through every query, traversal, and mutation – no casts, no runtime surprises.
import { Graph, GraphSchema, InMemoryGraphStorage } from "@codemix/graph";
import { z } from "zod";
const schema = {
vertices: {
User: {
properties: {
email: { type: z.email(), index: { type: "hash", unique: true } },
name: { type: z.string() },
},
},
Repo: {
properties: {
name: { type: z.string() },
stars: { type: z.number() },
},
},
},
edges: {
OWNS: { properties: {} },
FOLLOWS: { properties: {} },
},
} as const satisfies GraphSchema;
const graph = new Graph({ schema, storage: new InMemoryGraphStorage() });
- Any Standard Schema library – Zod, Valibot, ArkType, or your own.
- Validated on every mutation – properties are checked on
addVertex,addEdge, andupdateProperty. - Indexes declared inline – hash, B-tree, and full-text; built lazily and maintained incrementally.
Add some data
Vertices and edges are added through the graph instance. Property arguments are checked against your schema at both compile time and runtime.
const alice = graph.addVertex("User", { name: "Alice", email: "[email protected]" });
const bob = graph.addVertex("User", { name: "Bob", email: "[email protected]" });
const myRepo = graph.addVertex("Repo", { name: "my-repo", stars: 0 });
graph.addEdge(alice, "OWNS", myRepo, {});
graph.addEdge(bob, "FOLLOWS", alice, {});
Write type-safe queries
A Gremlin-style traversal API – familiar step names, but every label, property key, and hop is checked by TypeScript against your schema.
import { GraphTraversal } from "@codemix/graph";
const g = new GraphTraversal(graph);
for (const path of g.V().hasLabel("User")) {
path.value.get("name"); // string
}
Offline-first sync and realtime collaboration
Swap InMemoryGraphStorage for YGraph and the entire graph lives in a Yjs CRDT document. Every traversal, Cypher query, and index works unchanged – you just get conflict-free sync on top.
import * as Y from "yjs";
import { YGraph } from "@codemix/y-graph-storage";
const doc = new Y.Doc();
const graph = new YGraph({ schema, doc });
Cypher queries for APIs and LLMs
The same graph is queryable via a Cypher-compatible string language – ideal for exposing data to LLMs via an MCP server.
import { parseQueryToSteps, createTraverser } from "@codemix/graph";
const { steps, postprocess } = parseQueryToSteps(`
MATCH (u:User)-[:OWNS]->(r:Repo)
WHERE r.stars > 100
RETURN u.name, r.name
`);
Source: Hacker News















