Vite (React)
Build and query a ZXCV database from a Vite + React single-page app, then ship it to the edge. You’ll end with a component that lists live data in the browser.
A Vite SPA has no server, so it fetches from the browser. That’s fine here — the anon key is public and safe to ship, because access is enforced server-side by your authorization rules.
Create a project
In the dashboard click Start building, or run zxcv
from your terminal. Open Settings → API and copy your project ref and
anon key.
Create a table
In the SQL editor, create a todos table with a couple of rows:
create table todos (
id bigint generated always as identity primary key,
title text not null,
is_complete boolean not null default false
);
insert into todos (title) values ('Read the docs'), ('Ship an app');Install the SDK
npm
bash npm install @zxcv.build/sdkInitialize the client
Add your keys to .env. Vite only exposes variables prefixed with VITE_ to the
browser, which is exactly what the anon key needs:
VITE_ZXCV_PROJECT=acme-store
VITE_ZXCV_ANON_KEY=your-anon-keyCreate a shared client. In Vite you read env vars off import.meta.env:
import { createClient } from '@zxcv.build/sdk'
export const zxcv = createClient({
project: import.meta.env.VITE_ZXCV_PROJECT,
anonKey: import.meta.env.VITE_ZXCV_ANON_KEY,
})Fetch and render
There’s no server component, so fetch on the client inside useEffect:
import { useEffect, useState } from 'react'
import { zxcv } from './zxcv'
type Todo = { id: number; title: string; is_complete: boolean }
export function Todos() {
const [todos, setTodos] = useState<Todo[]>([])
useEffect(() => {
zxcv
.from('todos')
.select('id, title, is_complete')
.order('id')
.then(({ data, error }) => {
if (error) console.error(error)
else setTodos(data ?? [])
})
}, [])
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
)
}Render it from your app root:
import { Todos } from './Todos'
export default function App() {
return <Todos />
}Want live updates instead of a one-time fetch? Swap the useEffect for a
Realtime subscription — it’s the same client, and the
feed is filtered by the same authorization rules as select.
Deploy
Ship the built SPA to the global edge from your terminal:
npm i -g zxcv
zxcv link acme-store
zxcv deploy --prodEvery push gets a preview URL; --prod promotes to your domain. See
Deploy for custom domains and canaries.
Next steps
- Auth — add sign-in and row-level security
- Realtime — live updates in the browser
- SDK reference · Database