diff --git a/apps/docs/pages/guides/database/connecting-to-postgres.mdx b/apps/docs/pages/guides/database/connecting-to-postgres.mdx
index c48c8bba747..10f810293f8 100644
--- a/apps/docs/pages/guides/database/connecting-to-postgres.mdx
+++ b/apps/docs/pages/guides/database/connecting-to-postgres.mdx
@@ -233,13 +233,13 @@ This is the most granular option. Connections are returned to the pool after eve
- Navigate to the SSL tab and change the SSL mode to Require. Next navigate to the Root certificate input, it will open up a file-picker modal. Select the certificate you downloaded from your Supabase dashboard and save the server details. PgAdmin should now be able to connect to your Postgres via SSL.
+ Navigate to the Parameters tab and select connection parameter as Root Certificate. Next navigate to the Root certificate input, it will open up a file-picker modal. Select the certificate you downloaded from your Supabase dashboard and save the server details. PgAdmin should now be able to connect to your Postgres via SSL.
- 
+ 
diff --git a/apps/docs/pages/guides/getting-started/tutorials/with-flutter.mdx b/apps/docs/pages/guides/getting-started/tutorials/with-flutter.mdx
index 2978ec82638..3a7de36b332 100644
--- a/apps/docs/pages/guides/getting-started/tutorials/with-flutter.mdx
+++ b/apps/docs/pages/guides/getting-started/tutorials/with-flutter.mdx
@@ -34,49 +34,33 @@ Then let's install the only additional dependency: [`supabase_flutter`](https://
Copy and paste the following line in your pubspec.yaml to install the package:
```yaml
-supabase_flutter: ^1.0.0
+supabase_flutter: ^1.10.3
```
Run `flutter pub get` to install the dependencies.
### Setup deep links
-Now that we have the dependencies installed let's setup deep links so users who have logged in via magic link or OAuth can come back to the app.
+Now that we have the dependencies installed let's setup deep links.
+Setting up deep links is required to bring back the user to the app when they click on the magic link to sign in.
+We can setup deep links with just a minor tweak on our Flutter application.
-Add `io.supabase.flutterquickstart://login-callback/` as a new [redirect URL](https://app.supabase.com/project/_/auth/url-configuration) in the Dashboard.
+We will use `io.supabase.flutterquickstart` as the scheme, and `login-callback` as the host for our deep link in this example, but you can change it to whatever you would like.
+
+First, add `io.supabase.flutterquickstart://login-callback/` as a new [redirect URL](https://app.supabase.com/project/_/auth/url-configuration) in the Dashboard.

That is it on Supabase's end and the rest are platform specific settings:
-For Android, edit the `android/app/src/main/AndroidManifest.xml` file.
-
-Add an intent-filter to enable deep linking:
-
-```xml android/app/src/main/AndroidManifest.xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-For iOS, edit the ios/Runner/Info.plist file.
+
+
+Edit the `ios/Runner/Info.plist` file.
Add CFBundleURLTypes to enable deep linking:
@@ -103,9 +87,40 @@ Add CFBundleURLTypes to enable deep linking:
```
-For web:
+
+
+Edit the `android/app/src/main/AndroidManifest.xml` file.
+Add an intent-filter to enable deep linking:
+
+```xml android/app/src/main/AndroidManifest.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+
+
There are no additional configurations.
+
+
### Main function
@@ -115,44 +130,19 @@ These variables will be exposed on the app, and that's completely fine since we
```dart lib/main.dart
Future main() async {
- WidgetsFlutterBinding.ensureInitialized();
-
await Supabase.initialize(
url: 'YOUR_SUPABASE_URL',
anonKey: 'YOUR_SUPABASE_ANON_KEY',
+ authFlowType: AuthFlowType.pkce,
);
runApp(MyApp());
}
-```
-
-### Setting up some constants and handy functions
-
-Let's also create a constant file to make it easier to use Supabase client.
-We will also include an extension method declaration to call `showSnackBar` with one line of code.
-
-```dart lib/constants.dart
-import 'package:flutter/material.dart';
-import 'package:supabase_flutter/supabase_flutter.dart';
final supabase = Supabase.instance.client;
-
-extension ShowSnackBar on BuildContext {
- void showSnackBar({
- required String message,
- Color backgroundColor = Colors.white,
- }) {
- ScaffoldMessenger.of(this).showSnackBar(SnackBar(
- content: Text(message),
- backgroundColor: backgroundColor,
- ));
- }
-
- void showErrorSnackBar({required String message}) {
- showSnackBar(message: message, backgroundColor: Colors.red);
- }
-}
```
+`AuthFlowType.pkce` on `authFlowType` parameter indicates that we are using a secure [PKCE flow](https://supabase.com/blog/supabase-auth-sso-pkce#introducing-pkce) to perform our magic link login.
+
### Set up Splash Screen
Let's create a splash screen that will be shown to users right after they open the app.
@@ -160,7 +150,7 @@ This screen retrieves the current session and redirects the user accordingly.
```dart lib/pages/splash_page.dart
import 'package:flutter/material.dart';
-import 'package:supabase_quickstart/constants.dart';
+import 'package:supabase_quickstart/main.dart';
class SplashPage extends StatefulWidget {
const SplashPage({super.key});
@@ -170,20 +160,18 @@ class SplashPage extends StatefulWidget {
}
class _SplashPageState extends State {
- bool _redirectCalled = false;
@override
- void didChangeDependencies() {
- super.didChangeDependencies();
+ void initState() {
+ super.initState();
_redirect();
}
Future _redirect() async {
await Future.delayed(Duration.zero);
- if (_redirectCalled || !mounted) {
+ if (!mounted) {
return;
}
- _redirectCalled = true;
final session = supabase.auth.currentSession;
if (session != null) {
Navigator.of(context).pushReplacementNamed('/account');
@@ -199,7 +187,6 @@ class _SplashPageState extends State {
);
}
}
-
```
### Set up a Login page
@@ -215,8 +202,7 @@ import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
-
-import 'package:supabase_quickstart/constants.dart';
+import 'package:supabase_quickstart/main.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@@ -228,37 +214,46 @@ class LoginPage extends StatefulWidget {
class _LoginPageState extends State {
bool _isLoading = false;
bool _redirecting = false;
- late final TextEditingController _emailController;
+ late final TextEditingController _emailController = TextEditingController();
late final StreamSubscription _authStateSubscription;
Future _signIn() async {
- setState(() {
- _isLoading = true;
- });
try {
+ setState(() {
+ _isLoading = true;
+ });
await supabase.auth.signInWithOtp(
email: _emailController.text.trim(),
emailRedirectTo:
kIsWeb ? null : 'io.supabase.flutterquickstart://login-callback/',
);
if (mounted) {
- context.showSnackBar(message: 'Check your email for login link!');
+ ScaffoldMessenger.of(context).showSnackBar(
+ const SnackBar(content: Text('Check your email for a login link!')),
+ );
_emailController.clear();
}
} on AuthException catch (error) {
- context.showErrorSnackBar(message: error.message);
+ SnackBar(
+ content: Text(error.message),
+ backgroundColor: Theme.of(context).colorScheme.error,
+ );
} catch (error) {
- context.showErrorSnackBar(message: 'Unexpected error occurred');
+ SnackBar(
+ content: const Text('Unexpected error occurred'),
+ backgroundColor: Theme.of(context).colorScheme.error,
+ );
+ } finally {
+ if (mounted) {
+ setState(() {
+ _isLoading = false;
+ });
+ }
}
-
- setState(() {
- _isLoading = false;
- });
}
@override
void initState() {
- _emailController = TextEditingController();
_authStateSubscription = supabase.auth.onAuthStateChange.listen((data) {
if (_redirecting) return;
final session = data.session;
@@ -310,8 +305,7 @@ Let's create a new widget called `account_page.dart` for that.
```dart lib/pages/account_page.dart"
import 'package:flutter/material.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
-import 'package:supabase_quickstart/components/avatar.dart';
-import 'package:supabase_quickstart/constants.dart';
+import 'package:supabase_quickstart/main.dart';
class AccountPage extends StatefulWidget {
const AccountPage({super.key});
@@ -323,8 +317,8 @@ class AccountPage extends StatefulWidget {
class _AccountPageState extends State {
final _usernameController = TextEditingController();
final _websiteController = TextEditingController();
- String? _avatarUrl;
- var _loading = false;
+
+ var _loading = true;
/// Called once a user id is received within `onAuthenticated()`
Future _getProfile() async {
@@ -336,21 +330,28 @@ class _AccountPageState extends State {
final userId = supabase.auth.currentUser!.id;
final data = await supabase
.from('profiles')
- .select()
+ .select