Capsule API

Lakebed Native accepts the same server shapes as web Lakebed and the native array style.

Server (lakebed/server)

import {
  capsule, query, mutation, endpoint,
  table, string, boolean, number, json, text
} from "lakebed/server";

Web-style schema (recommended for cross-platform)

export default capsule({
  name: "my-app",
  schema: {
    todos: table({
      title: text(),
      done: boolean().default(false),
      userId: string(),
    }),
  },
  queries: {
    listTodos: query((ctx) =>
      ctx.db.todos.where("userId", ctx.auth.userId ?? "guest").all()
    ),
  },
  mutations: {
    addTodo: mutation((ctx, args: { title: string }) =>
      ctx.db.todos.insert({ title: args.title, userId: ctx.auth.userId ?? "guest", done: false })
    ),
  },
});

Native array style (still supported)

const todos = table("todos", { title: text(), done: boolean() });
export default capsule({
  name: "my-app",
  tables: [todos],
  queries: [query("listTodos", (ctx) => ctx.db.table("todos").all())],
  mutations: [mutation("addTodo", (ctx, args) => ctx.db.table("todos").insert(args))],
});

Context (web parity)

Field Web Lakebed Native
User id ctx.auth.userId ctx.auth.userId or ctx.auth.user?.id
Display name ctx.auth.displayName ctx.auth.displayName or ctx.auth.user?.name
Avatar ctx.auth.picture or ctx.auth.user?.avatarUrl
DB ctx.db.todos ctx.db.todos or ctx.db.table("todos")

Rows get auto id, createdAt, and updatedAt on insert/update. Field .default(value) is applied on insert.

Shared imports

Extensionless imports work in dev and build:

import { cleanTitle } from "../shared/habit";

HTTP / WS (local dev)

Client (lakebed-native/client)

import {
  useAuth, useQuery, useMutation, useConnection,
  authAs, signInWithGoogle, signOut, configureClient,
} from "lakebed-native/client";

useQuery(name, args?)

Returns { data, loading, error, refetch }:

const { data: todos, loading, error, refetch } = useQuery<Todo[]>("listTodos");
if (loading) return <Spinner />;
if (error) return <ErrorState title="Could not load" message={error.message} />;

useMutation(name, opts?)

Returns { mutate, loading, error }. Pass { onError, onSuccess } for UI handling.

useAuth()

Returns web-parity fields plus nested user:

{
  user: AuthUser | null;
  userId: string | null;
  displayName: string | null;
  picture: string | null;
  isGuest: boolean;
  loading: boolean;
  error: Error | null;
  refresh: () => Promise<void>;
}

Updates automatically on auth-changed (local WS) and hosted auth refresh. After authAs(), call refresh() if needed on HTTP-only paths.

Connection / offline

useConnection(){ status: "connected" | "disconnected" | "connecting", error, retry } for dead server / offline UX.

configureClient({ serverUrl: "http://localhost:3000" });

Assets

Place images under assets/ and reference by URI in dev, or use remote URLs:

import { Image } from "lakebed-native/ui";
<Image source={{ uri: "https://example.com/photo.jpg" }} />

Typecheck

npx lakebed-native typecheck

Runs tsc --noEmit on app/ and shared/.