# Add a backend to a Flutter app

> Give a Flutter app a Postgres database, auth and storage with supabase_flutter: create the project in one click, pass the URL and key with --dart-define.

Source: https://scribase.com/frameworks/flutter

npx scribase init is for JavaScript projects, so a Flutter app takes the manual path, which is short: create the project in the console, copy two values, and use the supabase_flutter package, which works with Scribase unchanged.

## Environment file: --dart-define

- SUPABASE_URL
- SUPABASE_ANON_KEY

## Create the backend

Sign up in the console (one click plus the $1 card check, credited back). Your first project is created automatically and the "Your backend is live" screen shows the Project URL and the publishable key with one-click copy.

## Add the package

supabase_flutter is the Dart client for this API; Scribase is wire-compatible with it.

```bash
flutter pub add supabase_flutter
```

## Initialize it at startup

Read the values from --dart-define so they never sit in source control.

_lib/main.dart_
```dart
import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Supabase.initialize(
    url: const String.fromEnvironment('SUPABASE_URL'),
    anonKey: const String.fromEnvironment('SUPABASE_ANON_KEY'),
  );
  runApp(const MyApp());
}

final supabase = Supabase.instance.client;
```

## Run with the two values

Or put them in a JSON file and pass --dart-define-from-file=env.json (and add env.json to .gitignore).

```bash
flutter run \
  --dart-define=SUPABASE_URL=https://acme-my-app-production-c2b0ea0a.scribase.com \
  --dart-define=SUPABASE_ANON_KEY=<publishable key>
```

## 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');
```

## Query from a widget

A FutureBuilder is enough for a first screen.

```dart
final todos = await supabase.from('todos').select('id, title');
// todos is a List<Map<String, dynamic>>: [{id: 1, title: 'Ship the backend'}, ...]
```

## Agent prompt

```
Add a Scribase backend to this Flutter app.
1. Add supabase_flutter with `flutter pub add supabase_flutter`.
2. Initialize it in lib/main.dart from String.fromEnvironment('SUPABASE_URL') and String.fromEnvironment('SUPABASE_ANON_KEY'); I will pass them with --dart-define-from-file=env.json. Create env.json with placeholder values and add it to .gitignore.
3. Create a `todos` table with row-level security on and a read policy using the Scribase MCP server or a SQL migration.
4. Show the todos on the home screen with a FutureBuilder. Never put the service role key in the app.
```

## FAQ

**Will npx scribase init support Flutter?**

It does not today; in a folder without package.json it would write a JavaScript client you do not need. Use the console path above, which takes about a minute.

**Do auth deep links work?**

Yes. Configure the redirect URL for your app scheme in the project auth settings, exactly as supabase_flutter documents.