Todo Example
This capsule shows the smallest useful Lakebed app pattern: authenticated per-user data with server-owned mutations.
What It Shows
- A
todostable withtext,done, andownerId. - A
todosquery filtered byctx.auth.userId. - An
addTodomutation that cleans input before insert. - A
setTodoDonemutation that checks row ownership before update. - A
clearDonemutation that deletes only the current user's completed rows. - A Preact UI using
useAuth,useQuery,useMutation, and<SignInWithGoogle />. - A pure shared helper for todo text normalization.
Server Pattern
queries: {
todos: query((ctx) =>
ctx.db.todos
.where("ownerId", ctx.auth.userId)
.orderBy("createdAt", "desc")
.all()
)
}
Use this pattern whenever rows belong to a single user. The client should not receive rows it does not own.
For mutations, fetch the row and check ownership before changing it:
const todo = ctx.db.todos.get(id);
if (!todo || todo.ownerId !== ctx.auth.userId) {
return;
}
ctx.db.todos.update(id, { done });
Run It
Run the checked-in example:
npx lakebed auth as alice
npx lakebed dev examples/todo
Open:
http://localhost:3000
To compare two users, open:
http://localhost:3000/?lakebed_guest=alice
http://localhost:3000/?lakebed_guest=bob
Then inspect state:
npx lakebed db dump --port 3000
npx lakebed logs --port 3000