Define the server
import { boolean, capsule, mutation, query, string, table } from "@luminaweb/runtime/server";
export default capsule({
schema: { todos: table({ text: string(), done: boolean(), ownerId: string() }) },
queries: {
todos: query((ctx) =>
ctx.db.todos.where("ownerId", ctx.auth.userId).orderBy("createdAt", "desc").all(),
),
},
mutations: {
addTodo: mutation((ctx, text: string) => {
const clean = text.trim().slice(0, 160);
if (!clean) return;
ctx.db.todos.insert({ text: clean, done: false, ownerId: ctx.auth.userId });
}),
setTodoDone: mutation((ctx, id: string, done: boolean) => {
const todo = ctx.db.todos.get(id);
if (!todo || todo.ownerId !== ctx.auth.userId) return;
ctx.db.todos.update(id, { done });
}),
},
});
Build the client
import { useAuth, useMutation, useQuery, SignInWithGoogle, signOut } from "@luminaweb/runtime/client";
export function App() {
const auth = useAuth();
const todos = useQuery<Todo[]>("todos");
const addTodo = useMutation<[text: string], void>("addTodo");
// ...
}
Auth
Use useAuth() on the client and ctx.auth on the server. Do not accept authorId or other trusted metadata from the client.