Skip to main content

Installation

Add the Supabase Flutter package to your pubspec.yaml:
dependencies:
  supabase_flutter: ^2.0.0
Then run:
flutter pub get

Initializing

Initialize Supabase in your app’s main function.
import 'package:supabase_flutter/supabase_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await Supabase.initialize(
    url: 'YOUR_SUPABASE_URL',
    anonKey: 'YOUR_SUPABASE_ANON_KEY',
  );

  runApp(MyApp());
}

final supabase = Supabase.instance.client;
url
String
required
The unique Supabase URL for your project.
anonKey
String
required
The Supabase anon key for your project.
authOptions
AuthClientOptions
Authentication configuration options.

Database Operations

Select Data

Query data from your tables.
final response = await supabase
  .from('countries')
  .select();
response
List<Map<String, dynamic>>
The returned rows from the query.

Select with Filters

final response = await supabase
  .from('countries')
  .select('name, capital')
  .eq('id', 1)
  .single();

Select with Joins

final response = await supabase
  .from('countries')
  .select('''
    name,
    cities (
      name,
      population
    )
  ''');

Common Filters

// Equal to
final data = await supabase
  .from('countries')
  .select()
  .eq('name', 'Albania');

// Not equal to
final data = await supabase
  .from('countries')
  .select()
  .neq('name', 'Albania');

// Greater than
final data = await supabase
  .from('countries')
  .select()
  .gt('population', 1000000);

// Less than
final data = await supabase
  .from('countries')
  .select()
  .lt('population', 1000000);

// Like (pattern matching)
final data = await supabase
  .from('countries')
  .select()
  .like('name', '%Alba%');

// In list
final data = await supabase
  .from('countries')
  .select()
  .inFilter('name', ['Albania', 'Algeria']);

Insert Data

Insert rows into your tables.
final response = await supabase
  .from('countries')
  .insert({
    'name': 'Denmark',
    'code': 'DK'
  })
  .select();
values
Map | List<Map>
required
The values to insert. Can be a single map or a list of maps.

Insert Multiple Rows

final response = await supabase
  .from('countries')
  .insert([
    {'name': 'Denmark', 'code': 'DK'},
    {'name': 'Norway', 'code': 'NO'}
  ])
  .select();

Update Data

Update existing rows in your tables.
final response = await supabase
  .from('countries')
  .update({'name': 'Australia'})
  .eq('id', 1)
  .select();
values
Map<String, dynamic>
required
The values to update.

Upsert Data

Insert or update rows based on unique constraints.
final response = await supabase
  .from('countries')
  .upsert({'id': 1, 'name': 'Australia'})
  .select();

Delete Data

Delete rows from your tables.
final response = await supabase
  .from('countries')
  .delete()
  .eq('id', 1);

Authentication

Sign Up

Create a new user account.
final response = await supabase.auth.signUp(
  email: 'example@email.com',
  password: 'example-password',
);
email
String
required
The user’s email address.
password
String
required
The user’s password.
data
Map<String, dynamic>
Additional user metadata.
emailRedirectTo
String
A URL to redirect to after signup.
response
AuthResponse

Sign In

Sign in an existing user.
final response = await supabase.auth.signInWithPassword(
  email: 'example@email.com',
  password: 'example-password',
);

Sign Out

Sign out the current user.
await supabase.auth.signOut();

Get Session

Get the current session.
final session = supabase.auth.currentSession;
session
Session?
The current session object or null if no active session.

Get User

Get the current user.
final user = supabase.auth.currentUser;
user
User?
The current user object or null if not authenticated.

Auth State Changes

Listen to authentication state changes.
supabase.auth.onAuthStateChange.listen((data) {
  final AuthChangeEvent event = data.event;
  final Session? session = data.session;
  
  if (event == AuthChangeEvent.signedIn) {
    // User signed in
  }
});

Storage

Upload File

Upload a file to a storage bucket.
import 'dart:io';

final file = File('path/to/file');
final response = await supabase.storage
  .from('avatars')
  .upload(
    'public/avatar1.png',
    file,
    fileOptions: const FileOptions(
      contentType: 'image/png'
    ),
  );
path
String
required
The file path including the file name.
file
File | Uint8List
required
The file data to upload.
fileOptions
FileOptions
Upload options.

Download File

Download a file from storage.
final data = await supabase.storage
  .from('avatars')
  .download('public/avatar1.png');
path
String
required
The file path to download.
data
Uint8List
The file data as bytes.

List Files

List all files in a bucket.
final files = await supabase.storage
  .from('avatars')
  .list(
    path: 'public',
    searchOptions: const SearchOptions(
      limit: 100,
      offset: 0,
      sortBy: SortBy(
        column: 'name',
        order: 'asc',
      ),
    ),
  );

Delete Files

Delete files from storage.
await supabase.storage
  .from('avatars')
  .remove(['public/avatar1.png', 'public/avatar2.png']);

Get Public URL

Get the public URL for a file.
final url = supabase.storage
  .from('avatars')
  .getPublicUrl('public/avatar1.png');

print(url);

Realtime

Subscribe to Changes

Listen to database changes in realtime.
final channel = supabase
  .channel('db-changes')
  .onPostgresChanges(
    event: PostgresChangeEvent.all,
    schema: 'public',
    table: 'countries',
    callback: (payload) {
      print('Change received: $payload');
    },
  )
  .subscribe();
event
PostgresChangeEvent
required
The database event to listen for: insert, update, delete, or all.
schema
String
required
The database schema to listen to.
table
String
required
The table to listen to.
callback
void Function(dynamic)
required
Function to call when an event occurs.

Unsubscribe

Stop listening to changes.
await supabase.removeChannel(channel);

Edge Functions

Invoke Function

Invoke a Supabase Edge Function.
final response = await supabase.functions.invoke(
  'hello-world',
  body: {'name': 'Functions'},
);

final data = response.data;
functionName
String
required
The name of the Edge Function to invoke.
body
Map<String, dynamic>
The request body to send to the function.
headers
Map<String, String>
Custom headers to send with the request.
method
HttpMethod
default:"HttpMethod.post"
HTTP method to use.
response
FunctionResponse

Error Handling

Handle errors using try-catch blocks:
try {
  final data = await supabase
    .from('countries')
    .select();
  print('Data: $data');
} on PostgrestException catch (error) {
  print('Database error: ${error.message}');
} catch (error) {
  print('Unexpected error: $error');
}
Handle deep links for OAuth and password recovery:
import 'package:app_links/app_links.dart';

final appLinks = AppLinks();

appLinks.uriLinkStream.listen((uri) {
  supabase.auth.getSessionFromUrl(uri);
});

Additional Resources

GitHub Repository

View the source code and contribute

pub.dev Package

View package details and versions