Quickstart
In this guide you create a posts table that each user can only read and write for themselves, then use the SDK to sign a test user in and work with rows.
Before you start
Section titled “Before you start”- Node.js 22 or later.
- A VAIF Studio account. Create one in the console.
- The
vaifCLI, signed in withvaif login. See Installation.
1. Create a project
Section titled “1. Create a project”In the console, choose New project and give it a name.
2. Create a table with a row rule
Section titled “2. Create a table with a row rule”Save this SQL in your app as migrations/0001_posts.sql:
-- vaif:owner author_idCREATE TABLE posts ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), author_id uuid NOT NULL, title text NOT NULL, content text, published boolean DEFAULT false, created_at timestamptz DEFAULT now());Then apply it to your project:
vaif db push --dir ./migrations --project-id <your-project-id>The -- vaif:owner author_id line above CREATE TABLE adds a row rule: each signed-in user reads, changes and deletes only the posts whose author_id is their own user id, and the server fills author_id on every new post.
You can also create the table on the console’s Schema page. A table made there has no rule yet; add one as described in Row rules.
3. Copy your project ID and key
Section titled “3. Copy your project ID and key”Open Security > Credentials in the console and copy the project ID and the publishable key (it starts with vk_pub_). Row rules apply to a publishable key, so it is safe in browser and app code. See API keys.
4. Install the SDK
Section titled “4. Install the SDK”Install @vaifstudio/client in your app:
npm install @vaifstudio/clientThe package works in browsers, Node.js 22 and later, React Native and edge runtimes. For other languages, see SDKs or call the REST API.
5. Connect, sign in and query
Section titled “5. Connect, sign in and query”import { createVaifClient } from "@vaifstudio/client";
// Columns the server fills (id, created_at, and author_id from the row rule)// are optional when you create a row.type Post = { id: string; author_id?: string; title: string; content: string | null; published: boolean; created_at?: string;};
let accessToken = "";
const vaif = createVaifClient({ baseUrl: "https://api.vaif.studio", projectId: process.env.VAIF_PROJECT_ID, apiKey: process.env.VAIF_PUBLISHABLE_KEY, // vk_pub_: row rules apply accessToken: () => accessToken,});
// Sign a test user in, so the row rule has someone to match.const email = "sam@example.com";const password = "a-long-unique-passphrase";await vaif.auth.signUp(email, password).catch(() => undefined); // already signed up: fineconst result = await vaif.auth.login(email, password);if ("accessToken" in result) accessToken = result.accessToken;
const posts = vaif.from<Post>("posts");
// Create a rowconst { data: post } = await posts.create({ title: "My first post", content: "Hello from VAIF!", published: true });console.log(post.id);
// Query with a filter, an order and a limitconst { data: published } = await posts .eq("published", true) .orderBy("created_at", "desc") .limit(10) .list();
console.log(published.length);A query is built with chained calls and runs when you call a method such as list(), first() or get(id). See Querying data.
The script uses the publishable key, as browser and app code does. The row rule limits it to the signed-in user’s posts, and fills author_id for you. Tables are closed to requests with no signed-in user; give a table that visitors may read a public rule.
Next steps
Section titled “Next steps”- Authentication: sign your users in.
- Row rules: decide who reads and writes each row.
- Realtime: get changes as they happen.
- AI app builders: build the frontend with an AI tool.
- Console API for agents and CI: set a project up without a browser.