Todo + RLS
A minimal todo app where each user only sees their own rows.
What you'll build
Sign up → create todos scoped to
uid() → list only your rows using the anon key + session.1. Schema
Run in SQL editor or Migrations:
schema.sql
CREATE TABLE todos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL,
title TEXT NOT NULL,
done BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX todos_user_id_idx ON todos (user_id);2. Policies
policies.sql
ALTER TABLE todos ENABLE ROW LEVEL SECURITY;
CREATE POLICY "users manage own todos"
ON todos
FOR ALL
TO authenticated
USING (uid() = user_id)
WITH CHECK (uid() = user_id);Or use the table editor → Policies tab (roles: authenticated, using/with check: uid() = user_id).
3. Client
Pick your framework — selection is remembered across examples.
app/todos/page.tsx
'use client';
import { useEffect, useState } from 'react';
import { createClient } from 'voltbase-js';
const voltbase = createClient(
process.env.NEXT_PUBLIC_VOLTBASE_URL!,
process.env.NEXT_PUBLIC_VOLTBASE_ANON_KEY!,
);
type Todo = { id: string; title: string; done: boolean };
export default function TodosPage() {
const [todos, setTodos] = useState<Todo[]>([]);
const [title, setTitle] = useState('');
useEffect(() => {
void load();
}, []);
async function load() {
const { data } = await voltbase
.from('todos')
.select('*')
.order('created_at', 'desc');
setTodos((data as Todo[]) ?? []);
}
async function addTodo() {
const user = voltbase.auth.getUser();
if (!user) {
await voltbase.auth.signUp({
email: 'you@example.com',
password: 'password123',
});
}
await voltbase.from('todos').insert({
user_id: voltbase.auth.getUser()!.id,
title,
});
setTitle('');
await load();
}
return (
<div>
<input value={title} onChange={(e) => setTitle(e.target.value)} />
<button onClick={() => void addTodo()}>Add</button>
<ul>
{todos.map((t) => (
<li key={t.id}>{t.title}</li>
))}
</ul>
</div>
);
}Need env + client setup first? See the matching framework quickstart.