Supabase Flutter

repository·main·Indexed 21 days ago

https://github.com/supabase/supabase-flutter

The official Flutter client library for interacting with Supabase services, including Postgrest, GoTrue, Realtime, and Storage. It provides tools for authentication (Email, OTP, OAuth, Anonymous, MFA, and Passkeys), database CRUD operations via PostgREST, and invoking Supabase Edge Functions.

Tokens
29.5K
Snippets
109
Records
127
Agent score
76%

What's inside supabase-flutter

  1. Overview of supabase_typegen

    main

    supabase_typegen is a command-line code generator designed to transform a Supabase database schema into typed Dart table definitions. These definitions are intended for use with Supabase client packages to provide type safety when interacting with your database.

    Note: As of the current version, this package is a placeholder on pub.dev to reserve the name. The actual code generator implementation is under development and is not yet functional.

  2. Use the storage_client package to interact with Supabase Storage

    main

    The storage_client is a Dart client library designed to allow developers to interact with Supabase Storage. It provides the necessary methods to manage files, buckets, and other storage-related operations within a Dart or Flutter application.

    For detailed API documentation and specific implementation guides, refer to the official Supabase documentation:

  3. Use the correct Supabase package for your environment

    main

    Choosing between supabase and supabase_flutter depends on your target environment:

    • Use supabase if you are working in a non-Flutter Dart environment, such as server-side Dart (e.g., Dart Edge).
    • Use supabase_flutter if you are developing a Flutter application.

    The supabase package is the core Dart client library designed for environments where Flutter's UI framework and plugin ecosystem are not present.

  4. Authentication methods in supabase_flutter

    main

    The authentication example demonstrates several sign-in methods available in supabase_flutter. The following patterns are used:

    • Email & password: Uses signUp, signInWithPassword, resetPasswordForEmail, and verifyOTP with OtpType.recovery followed by updateUser.
    • Magic link & email OTP: Uses signInWithOtp(email: ...) followed by verifyOTP(type: OtpType.email).
    • Phone (SMS OTP): Uses signInWithOtp(phone: ...) followed by verifyOTP(type: OtpType.sms).
    • OAuth social: Uses signInWithOAuth for providers like Google, GitHub, and Apple. This requires configuring a redirectTo deep link (e.g., io.supabase.authexample://login-callback/) to return the user to the app.
    • Anonymous: Uses signInAnonymously, which can later be upgraded to a permanent account using updateUser to add an email and password.
    • Multi-factor authentication (MFA): Uses auth.mfa.enroll, challengeAndVerify, listFactors, and unenroll to manage TOTP factors.
  5. Understand Supabase Realtime features in Flutter

    main

    The realtime_room example demonstrates how to combine the three core pillars of Supabase Realtime within a single Flutter application channel:

    1. Postgres Changes: Listen to database events (like INSERT or DELETE) on a specific table to keep local state in sync with the database without manual re-fetching. Use onPostgresChanges to subscribe to these events.
    2. Broadcast: Send and receive ephemeral, low-latency messages that are not persisted to the database. This is ideal for transient data like "typing indicators". Use sendBroadcastMessage to emit data and onBroadcast to listen for it.
    3. Presence: Track user state and availability within a channel to build live rosters or "who is online" features. Use track to share local state, onPresenceSync to listen for changes in the room, and presenceState to view the current state of all participants.
  6. Use Realtime for data updates

    main

    Realtime allows you to receive live updates from your database.

    Realtime as a Stream

    You can convert a database query into a Stream using .stream(primaryKey: [...]).

    Warning: When using StreamBuilder in Flutter, persist the stream in a StatefulWidget variable rather than constructing it inside the build method to prevent rapid rebuilds and connection loss.

    Postgres Changes

    Listen to specific table changes (Insert, Update, Delete) using onPostgresChanges on a channel.

    Broadcast

    Send low-latency messages between clients without hitting the database using sendBroadcastMessage and onBroadcast.

    // Realtime as a Stream
    class _MyWidgetState extends State<MyWidget> {
      final stream = supabase.from('countries').stream(primaryKey: ['id']);
    
      @override
      Widget build(BuildContext context) {
        return StreamBuilder<List<Map<String, dynamic>>>(stream: stream, builder: (context, snapshot) {
          // ...
        });
      }
    }
    
    // Postgres Changes
    final myChannel = supabase.channel('my_channel');
    myChannel
        .onPostgresChanges(
          event: PostgresChangeEvent.all,
          schema: 'public',
          table: 'countries',
          callback: (payload) {
            // Handle change
          },
        )
        .subscribe();
    
    // Broadcast
    await myChannel.sendBroadcastMessage(
      event: 'cursor-pos',
      payload: {'x': 30, 'y': 50},
    );
  7. Perform Native Apple Sign-in

    main

    To implement native Apple sign-in on iOS or macOS, use the sign_in_with_apple package alongside supabase_flutter.

    1. Follow sign_in_with_apple setup instructions for iOS/macOS.
    2. Add your app's Bundle ID to the Supabase Dashboard under Authentication -> Providers -> Apple.
    3. Generate a raw nonce, hash it using SHA-256, and pass both the raw and hashed versions to the Apple credential request.
    4. Use signInWithIdToken with OAuthProvider.apple to complete the Supabase authentication.
    import 'package:sign_in_with_apple/sign_in_with_apple.dart';
    import 'package:supabase_flutter/supabase_flutter.dart';
    
    /// Performs Apple sign in on iOS or macOS
    Future<AuthResponse> signInWithApple() async {
      final rawNonce = supabase.auth.generateRawNonce();
      final hashedNonce = sha256.convert(utf8.encode(rawNonce)).toString();
    
      final credential = await SignInWithApple.getAppleIDCredential(
        scopes: [
          AppleIDAuthorizationScopes.email,
          AppleIDAuthorizationScopes.fullName,
        ],
        nonce: hashedNonce,
      );
    
      final idToken = credential.identityToken;
      if (idToken == null) {
        throw const AuthException(
            'Could not find ID Token from generated credential.');
      }
    
      return signInWithIdToken(
        provider: OAuthProvider.apple,
        idToken: idToken,
        nonce: rawNonce,
      );
    }
  8. Run the Passkeys example

    main

    You can run the passkey example locally using the provided launcher, or connect it to a specific Supabase project using --dart-define flags.

    Option 1: Using the examples launcher

    This boots a local Supabase stack and runs the example with pre-configured credentials.

    cd examples
    ./run.sh

    Option 2: Running against a hosted project

    Pass your project's URL and publishable key as --dart-defines.

    flutter run -d chrome \
      --dart-define=SUPABASE_URL=https://YOUR_PROJECT.supabase.co \
      --dart-define=SUPABASE_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY

    Note: Passkeys are bound to the domain (relying party) they were created on. A passkey registered on localhost will not work on a different domain.