scribase
One command + one edit

Add a backend to a React Native app with one command

init detects a React Native app (react-native plus app.json) and uses the Expo conventions: EXPO_PUBLIC_ variables in .env. Bare React Native CLI apps do not read those at build time, so there is one small edit. Using Expo? Follow the Expo guide instead; it needs no edit.

What you see (your project URL will differ)terminal
$ npx scribase init
Backend ready: https://acme-my-app-production-c2b0ea0a.scribase.com
  framework   expo
  project     acme/my-app (production)
  env file    .env (EXPO_PUBLIC_SUPABASE_URL, EXPO_PUBLIC_SUPABASE_ANON_KEY, SCRIBASE_API_URL, SCRIBASE_ORG, SCRIBASE_PROJECT, SCRIBASE_ENV)
  client      lib/supabase.ts

Next:
  - import { supabase } from './lib/supabase' and query: await supabase.from('todos').select()
  - create tables with SQL migrations (supabase/migrations/*.sql) and `scribase db push`, or the MCP server

1.Run init

Run it in the project root. If you are not signed in, it prints a link and a code: approve it in the browser (sign up takes one click plus the $1 card check, credited back), and init carries on. No key is ever pasted. It creates the project, writes the env file, adds the env file to .gitignore, installs @supabase/supabase-js and writes a small client module.

bash
npx scribase init

2.Put the two public values in a config module

Metro without Expo does not replace process.env.EXPO_PUBLIC_ values, so the generated client would get undefined. Copy the URL and the publishable key from .env into a small module. Both are public by design (they ship in every client build); row-level security protects the data.

lib/supabase.tsts
import 'react-native-url-polyfill/auto';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { createClient } from '@supabase/supabase-js';

const SUPABASE_URL = 'https://acme-my-app-production-c2b0ea0a.scribase.com'; // from .env
const SUPABASE_ANON_KEY = '<publishable key>'; // from .env

export const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
  auth: { storage: AsyncStorage, autoRefreshToken: true, persistSession: true, detectSessionInUrl: false },
});

3.Install the two native helpers

AsyncStorage keeps sessions across restarts and the URL polyfill fills a gap in the React Native runtime. Then run `npx pod-install` for iOS.

bash
npm install @react-native-async-storage/async-storage react-native-url-polyfill

4.Create your first table

Open your project in the console, go to Editor, then SQL, and run this. Or ask your coding agent: with the Scribase MCP server connected it applies the same SQL as a migration. Row-level security is on, so the public key can only read what the policy allows.

sql
create table public.todos (
  id bigint generated always as identity primary key,
  title text not null,
  done boolean not null default false,
  created_at timestamptz not null default now()
);

alter table public.todos enable row level security;

create policy "todos are readable" on public.todos
  for select to anon, authenticated using (true);

insert into public.todos (title) values ('Ship the backend'), ('Tell a friend');

5.Query it

Any screen can now read and write through the client.

App.tsxtsx
const { data: todos, error } = await supabase.from('todos').select('id, title');
if (error) console.warn(error.message);
Let your agent do it

Paste this into Claude Code, Cursor or Codex

The agent runs init, asks you to approve once in the browser, creates the table and wires up the first screen.

React Native setup promptprompt
Add a Scribase backend to this bare React Native CLI app.
1. Run `npx scribase init --yes --json` in the project root. If it returns authorization_pending, show me the link and code, wait for me to approve, then run it again.
2. Create a `todos` table (id, title, done, created_at) with row-level security on and a policy that lets anyone read it; use the Scribase MCP server or a SQL migration, not the service-role key in app code.
3. Rewrite lib/supabase.ts to read the URL and publishable key as constants copied from .env (never the service role key), add AsyncStorage and react-native-url-polyfill, and list the todos on the first screen.
4. Never print, log or commit the env file; it is already in .gitignore.

Connect the MCP server first so the agent can run SQL safely: connect your agent.

FAQ

Common questions

Is it safe to put the key in source code?

The publishable (anon) key, yes: it ships in every client build anyway and can only reach rows your policies allow. Never put the service role key in an app.

Can I use react-native-config instead?

Yes. Rename the two variables in .env to whatever your config library expects and read them from there.

Your React Native backend, live in a minute

$9 a month per project, flat. Sign up with one click; the $1 card check is credited to your first invoice.

Start now