Connect Your Frontend
This page gives you a drop-in API client and copy-paste examples for sign-up, login, and CRUD.
Using a coding agent?
API client
Put this in src/lib/api.js or src/lib/api.ts. It handles auth headers, token refresh on 401, and JSON parsing.
js
export const API = 'http://localhost:8787/api/v1'
export const session = {
token: '',
refreshToken: '',
userId: '',
}
export function setSession(payload) {
session.token = payload.token
session.refreshToken = payload.refresh_token
session.userId = payload.record?.id || ''
}
export function clearSession() {
session.token = ''
session.refreshToken = ''
session.userId = ''
}
async function readBody(res) {
const text = await res.text()
try {
return text ? JSON.parse(text) : null
} catch {
return text
}
}
export async function refreshSession() {
if (!session.token || !session.refreshToken) {
throw new Error('No session to refresh')
}
const res = await fetch(`${API}/table/users/auth/refresh-token`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${session.token}`,
},
body: JSON.stringify({
refresh_token: session.refreshToken,
}),
})
const data = await readBody(res)
if (!res.ok) {
throw new Error(typeof data === 'string' ? data : JSON.stringify(data))
}
setSession(data)
return data
}
export async function request(path, { method = 'GET', body, auth = true, retry = true } = {}) {
const res = await fetch(`${API}${path}`, {
method,
headers: {
...(body ? { 'Content-Type': 'application/json' } : {}),
...(auth && session.token ? { Authorization: `Bearer ${session.token}` } : {}),
},
body: body ? JSON.stringify(body) : undefined,
})
if (res.status === 401 && auth && retry && session.refreshToken) {
await refreshSession()
return request(path, { method, body, auth, retry: false })
}
const data = await readBody(res)
if (!res.ok) {
throw new Error(typeof data === 'string' ? data : JSON.stringify(data))
}
return data
}
export async function signUp(values) {
const data = await request('/table/users/auth/sign-up', {
method: 'POST',
auth: false,
body: values,
})
setSession(data)
return data
}
export async function login(identity, password) {
const data = await request('/table/users/auth/login-password', {
method: 'POST',
auth: false,
body: { identity, password },
})
setSession(data)
return data
}
export async function logout() {
await request('/table/users/auth/logout', {
method: 'POST',
})
clearSession()
}Sign up
With the default scaffold, name and passwordConfirm are required.
js
import { signUp } from './lib/api.js'
const session = await signUp({
username: 'alice',
email: 'alice@example.com',
password: 'secret123',
passwordConfirm: 'secret123',
name: 'Alice',
})
console.log(session.record.id)Log in
js
import { login } from './lib/api.js'
await login('alice@example.com', 'secret123')identity accepts either email or username.
Protected requests
js
import { request } from './lib/api.js'
const me = await request('/table/users/select?limit=1')
console.log(me)The client sends Authorization: Bearer <token> automatically.
CRUD
Read public posts
js
import { request } from './lib/api.js'
const posts = await request('/table/posts/select?where=published==true&order=-created&limit=20', {
auth: false,
})Create a post
If your rule is createRule: 'auth.uid == author', the insert must include the signed-in user's ID as author.
js
import { request, session } from './lib/api.js'
const created = await request('/table/posts/insert', {
method: 'POST',
body: {
values: {
title: 'Hello world',
body: 'My first post',
author: session.userId,
published: true,
},
returning: '*',
},
})
console.log(created[0].id)Update records
js
import { request, session } from './lib/api.js'
await request('/table/posts/update', {
method: 'POST',
body: {
where: `author == '${session.userId}' & published == false`,
setValues: {
published: true,
},
returning: '*',
},
})Edit one record by ID
js
import { request } from './lib/api.js'
await request('/table/posts/edit/POST_ID_HERE', {
method: 'POST',
body: {
title: 'Updated title',
},
})Delete records
js
import { request, session } from './lib/api.js'
await request('/table/posts/delete', {
method: 'POST',
body: {
where: `author == '${session.userId}' & published == false`,
returning: '*',
},
})