Skip to Content

Expo

Build and query a ZXCV database from a React Native app built with Expo. You’ll end with a screen that reads live data and renders it in a FlatList.

AI Assistance
Help me connect ZXCV to my Expo (React Native) app. Do the following:
1. Install the @zxcv.build/sdk package.
2. Initialize a client with my project ref + anon key (from Settings → API), using Expo's env convention (EXPO_PUBLIC_ prefix in .env, read off process.env).
3. Fetch rows from a "todos" table in a useEffect and render them with a FlatList.
4. Keep the anon key on the client — authorization is enforced server-side by my policies.
Ask me for my project ref and anon key if I haven't given them.

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 — the anon key is public and safe to ship in your app, because access is enforced server-side by your authorization rules.

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

bash npm install @zxcv.build/sdk

Initialize the client

Add your keys to .env. The EXPO_PUBLIC_ prefix exposes them to your app bundle, which is fine for the anon key:

.env
EXPO_PUBLIC_ZXCV_PROJECT=acme-store EXPO_PUBLIC_ZXCV_ANON_KEY=your-anon-key

Create a shared client you can import from anywhere:

lib/zxcv.ts
import { createClient } from '@zxcv.build/sdk' export const zxcv = createClient({ project: process.env.EXPO_PUBLIC_ZXCV_PROJECT!, anonKey: process.env.EXPO_PUBLIC_ZXCV_ANON_KEY!, })

EXPO_PUBLIC_ vars are inlined at build time. Restart the dev server after editing .env so Expo picks up the new values.

Fetch and render

Fetch in a useEffect when the screen mounts, hold the rows in state, and render them with a FlatList:

app/index.tsx
import { useEffect, useState } from 'react' import { FlatList, Text, View } from 'react-native' import { zxcv } from '../lib/zxcv' type Todo = { id: number; title: string; is_complete: boolean } export default function Index() { 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 ( <FlatList data={todos} keyExtractor={(todo) => String(todo.id)} renderItem={({ item }) => ( <View style={{ padding: 16 }}> <Text>{item.title}</Text> </View> )} /> ) }

Deploy

Ship the web build to the global edge from your terminal:

npm i -g zxcv zxcv link acme-store zxcv deploy --prod

Every push gets a preview URL; --prod promotes to your domain. See Deploy for custom domains and canaries.

Next steps