Shipping today

How to build and deploy Trellis apps before the full local-first stack is turnkey — without vendor kernel backends.

You can ship with Trellis today. What you cannot do — by design — is point Trellis at Convex, Firebase, or Neon as the authoritative op store. That gap is the awkward middle between Trellis's thesis and the BaaS-shaped market.

This guide is the practitioner companion to ADR 0039 (no vendor kernel backends; compatibility bridge instead) and ADR 0040 (lane boundary, open engine, hosted Platform sibling) in the trellis package at docs/adr/0039-no-vendor-kernel-backends-compatibility-bridge.md and docs/adr/0040-lane-boundary-oss-and-hosted-platform.md.

The question behind the question

You might askWhat you usually mean
"Do we have a Convex adapter?""Can I get live data without running infra?"
"Can Trellis use our Postgres?""Can we keep our warehouse/ops team happy?"
"What about Jazz/InstantDB?""Can I get that DX without their storage?"

The answers:

  1. Live app data → vendor BaaS (Jazz, InstantDB, Convex) or Trellis kernel if you need causal graph semantics — see Trellis and BaaS
  2. Analytics / BI → one-way export, never the write path
  3. DX on Trellis graphtyped SDK; for app-only rows, use your BaaS

Three layers (don't mix them)

Rendering Chart
LayerPackageWrites to op log?Use for
Durable graphtrellis, trellis/syncYesIssues, entities, audit, merge
Typed live readstrellis/schema, trellis/clientYes (reads persisted state)Nav, CMS, boards
Ephemeraltrellis/realtimeNoPresence, cursors, chat

Confusing sync with realtime is the most common integration mistake. See Collaboration & Sync and Realtime (ephemeral).

Paths that work now

Path A — Hosted Trellis (fastest multiplayer)

Best when: you want Jazz-like live UI without operating a server.

  1. Provision a Sprite or Trellis Cloud workspace
  2. Point the client at your room URL:
import { liveEntities } from "trellis/client";
import { TrellisDb } from "trellis/client/sdk";

import { Task } from "./schema";

const client = new TrellisDb({
  url: "https://myapp.sprites.app",
  apiKey: process.env.TRELLIS_API_KEY,
});

const tasks = liveEntities(client, Task);
tasks.start();
  1. Use framework hooks (trellis/react/typed, etc.) in the UI
  2. Mount relay for presence if needed (presenceRelay on deploy — see changelog ADR 0016)

Sovereignty check: you still own exportable .trellis state; the host relays and accelerates — it is not a substitute kernel hidden behind a vendor row store.

Path B — Local kernel + git (fastest solo / agent work)

Best when: agents, CLI, offline-first, file-centric repos.

trellis init
trellis watch          # file ops → graph
trellis issue start TRL-1

Git owns file bytes (4.0+); the op-log holds semantics. See Git bridge and Agent coordination.

Gap today: typed live reads in local embedded mode are still remote-only for WebSocket subscriptions. For local-only UIs, poll trellis query or run db serve and use Path A against localhost.

Path C — Self-hosted server

Best when: you control infra but want the same stack as Sprites.

trellis serve --port 8230
# client: TrellisDb({ url: 'http://localhost:8230' })

PartyKit or a Durable Object relay can front sync/presence without owning ops — see demo/partykit/ and Collaboration & Sync.

Path D — Relay-only third-party cloud

Best when: you already pay for Cloudflare / PartyKit and need cross-tab or cross-browser realtime without durable graph writes there.

  • trellis/realtime + WebSocketRelayTransport or DurableObjectRelayTransport
  • trellis/sync + PartyKitRoomTransport or IrohSyncTransport

The vendor moves bytes. Your SQLite kernel (or hosted Trellis) still authors ops.

This is the only sanctioned use of "adapters" to commercial realtime infra.

Best when: you need signup-speed app UI and auditable agent memory.

  1. App UI on Jazz, InstantDB, or Convex — live rows, auth, multiplayer
  2. Agents on Trellis — lanes, issues, decision traces, repo semantics
  3. Link by ID — wiki-links, issue refs; no dual-write

Full pattern, decision table, and anti-patterns: Trellis and BaaS.

For a hosted Rox-shaped product (you operate the stack): see Platform brief in docs/product/platform-brief.md (ADR 0040).

What we explicitly do not ship

Non-goalWhy
KernelBackend on Convex / Firebase / NeonVendor becomes source of truth
Dual-write Trellis + vendor DBHidden state, conflict hell
"Trellis Lite" on someone else's row storeMarkets as Trellis, locks like BaaS

If a feature fails the vision test — disconnect the network; does the system still function fully? — a vendor backend made it load-bearing. Roll back.

Bridging from an existing BaaS

You are not stuck forever; you are parallel-running or migrating:

  1. New features on Trellis — greenfield graph entities via typed SDK
  2. Legacy reads — keep vendor app on life support; Trellis owns new domains
  3. Export for analytics — warehouse ETL from Trellis snapshots/JSONL; one-way
  4. Cutover — when Trellis covers the domain, retire vendor writes

There is no drop-in adapter. Plan for a domain boundary, not a flip of DATABASE_URL.

Current gaps (honest)

GapWorkaround todayDirection
Local typed live readsdb serve + remote client URLEmbedded-kernel subscriptions
Empty remote bootstrapManual push / ADR 0028 draftrealtime-sync bootstrap
One-click onboardingSprites / StudioHosted Trellis polish
BaaS console ergonomicsStudio + graph explorerProjections, not vendor UI

Decision tree

Need durable multiplayer graph state on Trellis semantics?
├─ Yes → Trellis kernel (local, self-hosted, or Sprites)
│         └─ Need live UI? → typed SDK + /realtime (remote mode today)
├─ Need fast app UI + agent audit?
│         └─ Path E: BaaS + Trellis sidecar (see trellis-and-baas)
├─ Only presence/cursors/chat?
│         └─ trellis/realtime + relay (vendor OK as pipe)
└─ Only analytics on Trellis data?
          └─ export / ETL (one-way, async)