Dashboard

Use Voltbase with Expo

Create a Voltbase project, add sample data, and query it from an Expo React Native app.

1. Create a Voltbase project

  1. Sign up or sign in
  2. Create an organization and a project
  3. Open API and copy the Project URL, anon key, and (for server-only writes) the service role key
You can also create projects from the dashboard after signing in — no CLI required for this quickstart.

2. Set up your database

In the dashboard, open Database and create a instruments table (or run SQL):

schema.sql
create table instruments (
  id bigint generated always as identity primary key,
  name text not null
);

insert into instruments (name)
values ('violin'), ('viola'), ('cello');

alter table instruments enable row level security;

create policy "public read"
on instruments for select
to anon
using (true);

Why RLS?

With a public SELECT policy for anon, the browser anon key can read rows. Writes still need auth policies or the service role on the server.

3. Create a Expo app

terminal
npx create-expo-app@latest voltbase-expo --template blank-typescript
cd voltbase-expo

4. Declare environment variables

Create .env at the project root and paste your dashboard values:

.env
EXPO_PUBLIC_VOLTBASE_URL=https://YOUR_API/api/projects/YOUR_SLUG
EXPO_PUBLIC_VOLTBASE_ANON_KEY=your-anon-key
Restart the Expo bundler after changing env vars. Only EXPO_PUBLIC_* values are available in the app.

Keep the service role server-only

Never put the service role key in client bundles. Use the anon key in the browser; use the service role only in server routes, Server Components, or backend jobs.

5. Create a Voltbase client

Install the SDK, then add a small helper:

terminal
npm install voltbase-js
lib/voltbase.ts
import { createClient } from 'voltbase-js';

export const voltbase = createClient(
  process.env.EXPO_PUBLIC_VOLTBASE_URL!,
  process.env.EXPO_PUBLIC_VOLTBASE_ANON_KEY!,
);

6. Query Voltbase from Expo

Fetch rows from instruments and render them:

App.tsx
import { useEffect, useState } from 'react';
import { Text, FlatList, Text } from 'react-native';
import { voltbase } from './lib/voltbase';

type Instrument = { id: number; name: string };

export default function App() {
  const [rows, setRows] = useState<Instrument[]>([]);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    void (async () => {
      const { data, error } = await voltbase
        .from('instruments')
        .select('id, name')
        .order('id', 'asc');
      if (error) setError(error.message);
      else setRows((data as Instrument[]) ?? []);
    })();
  }, []);

  if (error) return <Text>{error}</Text>;

  return (
    <FlatList
      data={rows}
      keyExtractor={(item) => String(item.id)}
      renderItem={({ item }) => <Text>{item.name}</Text>}
      contentContainerStyle={{ padding: 24 }}
    />
  );
}

Next: Auth, Realtime, or the Todo + RLS example.