Typed SDK (live graph reads)
defineType to registerType to liveEntities typed, hydrated, real-time reads on persisted graph data.
Trellis 3.2 adds a typed SDK for building live UIs on the persisted semantic graph: one schema definition drives ontology registration, TypeScript types, EQL subscriptions, relation resolve, and framework hooks.
This is distinct from Realtime (ephemeral) (presence, chat, cursors, not in the op log) and from Collaboration & Sync (peer op replication).
When to use it
| Need | Use |
|---|---|
| Live sidebar, CMS collections, nav trees on graph entities | Typed SDK |
| Cursors, typing indicators, disposable chat | trellis/realtime |
| Audit trail, merge, offline peer sync | trellis/sync + VCS |
Architecture
defineType: Zod fields + relations → schema handle (Schema API).registerType: POST ontology to server (idempotent).liveEntities/liveEntitysubscribe with server-side hydration + optionalresolve.- Framework hook
trellis/vue/typed(or React / Svelte) binds signals to your UI.
Quickstart
1. Schema
// schema.ts
import { defineType, rel } from "trellis/schema";
import { z } from "zod";
export const Task = defineType(
"Task",
{ title: z.string(), done: z.boolean() },
{ title: "title" }
);
2. Server + client
npm install trellis@^3.2.0
npx trellis init
npx trellis serve --port 8230
import { TrellisDb } from "trellis/client/sdk";
const client = new TrellisDb({ url: "http://localhost:8230" });
await client.registerType(Task);
3. Live list (framework-agnostic)
import { liveEntities } from "trellis/client";
const tasks = liveEntities(client, Task, { where: { done: false } });
tasks.start();
4. Vue component
import { useEntities, useMutation } from "trellis/vue/typed";
const { data, loading } = useEntities(client, Task);
const task = useMutation(client, Task);
See Typed framework bindings for React and Svelte.
Relation resolve
Load a parent type and expand children in one subscription pass:
useEntities(client, NavSection, { resolve: { items: true } });
The server batches child loads grouped by foreign key. Client-side N+1 is avoided when the server marks the push as resolved.
Filters
List queries accept field equality or explicit operators:
import { whereCondition } from "trellis/schema";
liveEntities(client, Task, {
where: whereCondition("order", "gte", 1),
});
Supported ops: eq (default), ne, gt, gte, lt, lte, in.
Single entity by id
liveEntity uses read(id) for first paint, then an id-scoped subscription (entityQuery), not a full-type scan.
import { useEntity } from "trellis/vue/typed";
const { data: task } = useEntity(client, Task, taskId);
Try the parity demo
The graph-nav example (trellis repo) exercises the full stack across three frameworks:
git clone https://github.com/trentbrew/trellis.git
cd trellis
just graph-nav
| URL | Framework |
|---|---|
http://localhost:4200/react/ | React + trellis/react/typed |
http://localhost:4200/vue/ | Vue + trellis/vue/typed |
http://localhost:4200/svelte/ | Svelte + trellis/svelte/typed |
Open the same URL in two browser tabs; add a nav section in one tab and watch the other update.
Hosting notes
| Surface | Requirement |
|---|---|
| trellis.computer docs embeds | Static demos only (no live typed SDK on Vercel static hosting) |
| Your app | Long-lived trellis serve or Sprites deploy; WebSocket /realtime |
| Cross-browser ephemeral UI | Optional relay (trellis/realtime), not required for typed reads |
Studio and Trellis Cloud sandboxes run the full stack inside E2B; see Cloud hosting.