JavaScript quickstart
Read and write a table, and sign a user in by phone. The client is plain TypeScript with no framework dependency, so these steps are the same in React, Vue, Nuxt, SvelteKit, Astro and SolidJS.
1. A project and a table
Create a project in the dashboard and copy its publishable key (it starts aq_pub_), which is safe in a browser or a mobile app. In the SQL editor:
create table todos ( id bigint generated always as identity primary key, user_id uuid not null default auth.uid(), title text not null, done boolean not null default false ); alter table todos enable row level security; create policy "own rows" on todos for all to authenticated using (auth.uid() = user_id) with check (auth.uid() = user_id); grant select, insert, update, delete on todos to authenticated;
2. Install
npm install @affineq/js
import { createClient } from "@affineq/js";
const affineq = createClient("aq_pub_...");
The key names the project, so there is no URL to configure. Works in Node 18+, every modern browser, Deno, Bun and edge runtimes.
3. Read and write
const { data, error } = await affineq.from("todos").select("id, title, done").order("id");
await affineq.from("todos").insert({ title: "buy milk" });
await affineq.from("todos").update({ done: true }).eq("id", 1);
await affineq.from("todos").delete().eq("id", 1);
Until someone is signed in, the policy above returns nothing: that is row-level security doing its job. Every call resolves to { data, error, count, status } and never throws, and an error carries a code, a message and a resolution.
4. Sign a user in
Phone first: add a test number with a fixed code under Authentication → Providers → Phone (for example +254700000001 and 123456), then:
await affineq.auth.signInWithOtp({ phone: "+254700000001" });
const { data, error } = await affineq.auth.verifyOtp({ phone: "+254700000001", token: "123456", type: "sms" });
From then on every from() call carries the user’s token, so the policy returns their rows. The session persists and refreshes itself. For real codes, add your own SMS provider (Mobitech, Africa’s Talking or Twilio) on the same Phone card: you add the key, we handle the rest.
Where next
- Server-rendered? The Next.js quickstart keeps the session in cookies so a Server Component can read it.
- Other sign-in methods, storage, live updates and Workers are in the reference.
- Social sign-in (Google, GitHub, X, LinkedIn and more) is switched on under Authentication → Providers: Authentication.