Todo app
The smallest template, for learning how an app reads and writes rows. It adds src/lib/vaif.ts to a React app built with Vite: the client, with the publishable key, and four typed helpers for a todos table, getTodos, addTodo, toggleTodo and deleteTodo.
Create the app
Section titled “Create the app”vaif init --template todo-appRun it in your app's folder. It writes vaif.config.json and the template's files there. It stops if the folder already has a vaif.config.json, and leaves any other file that already exists alone; --force overwrites both.
It asks which features to include. This template has files for Database and Functions; Database is selected to start with. To skip the question, name them: vaif init --template todo-app --features database,functions. Add one later with vaif init --template todo-app --add-features <feature>.
What it writes
Section titled “What it writes”| File | Written |
|---|---|
src/lib/vaif.ts | Always |
drizzle/0002_todos.sql | Always |
.env.example | Always |
README.md | Always |
drizzle/0001_initial.sql | With Database |
drizzle.config.ts | With Database |
src/db/schema.ts | With Database |
functions/hello.ts | With Functions |
Install
Section titled “Install”This template adds files to an app you already have, and writes no package.json. Install the packages its files import:
npm install @vaifstudio/client @vaifstudio/reactConfigure
Section titled “Configure”Copy .env.example to .env and fill it in. The project ID and the keys are on Security > Credentials in the console.
| Variable | Value |
|---|---|
VITE_VAIF_API_URL | The API address. Keep the value in the file, https://api.vaif.studio. |
VITE_VAIF_PROJECT_ID | Your project ID, for the app. |
VITE_VAIF_PUBLISHABLE_KEY | The project's publishable key (vk_pub_). Row rules apply to it, so it is safe in an app. |
Set up the database
Section titled “Set up the database”The template writes two SQL files for your database, applied in name order. The comment line above each CREATE TABLE sets that table's row rules.
drizzle/0001_initial.sql, written with the Database feature, is an example: edit it to describe your own tables before you apply it.
-- Initial migration. Customize this schema for your project; vaif db push-- applies it. The comment directly above each CREATE TABLE sets that table's-- row rules: here each signed-in user reads and changes only their own rows,-- and the owner column is filled in from their sign-in on insert. Keep a rule-- comment on every table you add: a table with no row rules is closed to-- signed-out visitors but open to every signed-in user.
-- vaif:owner idCREATE TABLE IF NOT EXISTS "users" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(), "email" text NOT NULL UNIQUE, "name" text, "created_at" timestamp with time zone NOT NULL DEFAULT now());
-- vaif:owner user_idCREATE TABLE IF NOT EXISTS "posts" ( "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(), "user_id" uuid NOT NULL REFERENCES "users"("id"), "title" text NOT NULL, "content" text, "published" boolean NOT NULL DEFAULT false, "created_at" timestamp with time zone NOT NULL DEFAULT now());users(-- vaif:owner id): each signed-in user reads and changes only their own rows, andidis filled in from their sign-in.posts(-- vaif:owner user_id): each signed-in user reads and changes only their own rows, anduser_idis filled in from their sign-in.
drizzle/0002_todos.sql, written every time:
-- Todos, applied by vaif db push. Each signed-in user reads and changes-- only their own todos; user_id is filled in from their sign-in on insert.
-- vaif:owner user_idCREATE TABLE IF NOT EXISTS "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" timestamp with time zone NOT NULL DEFAULT now());todos(-- vaif:owner user_id): each signed-in user reads and changes only their own rows, anduser_idis filled in from their sign-in.
Put your project ID in vaif.config.json ("projectId"), sign in, and apply them. With no --dir, vaif db push finds the template's SQL folder, or a ./migrations folder, and applies its .sql files in name order.
vaif loginvaif db push --dry-run # what each file would changevaif db pushThe server fills in user_id on every new todo, which is why addTodo leaves it out. See Row rules.
Requests from a visitor who is not signed in are refused on a table without a public rule, so sign the user in before calling the helpers. See Authentication.
Next steps
Section titled “Next steps”- Querying data for the filters and ordering the helpers use.
vaif generatewrites TypeScript types for your tables, to replace theTodointerface insrc/lib/vaif.ts. See Installation.