User onboarding for Flutter.
Integrate the Fluo SDK in minutes and get a complete UI flow to authenticate and register your users.
UX principles
- Passwordless
- Single input screens
- Seamless authentication
Auth methods
Method | Status | Note |
---|---|---|
Email + Code | ✔️ Done | Fluo sends emails on your behalf using your app name |
Google Sign-in | ✔️ Done | Set it up in the Fluo dashboard |
Sign in with Apple | Not done | Plan is to ship by the end of April |
Mobile + Code | Not done | Plan is to ship in May |
Registration
- Intuitive "get or create user" logic
- Collect first name, last name, both, or none
- Integration with Firebase
- Integration with Supabase
STEP 1 — Get an api key from the Fluo dashboard
STEP 2 — Add the package to your dependencies:
flutter pub add fluo
STEP 3 — Add the FluoOnboarding
component in your app:
import 'package:fluo/fluo_onboarding.dart';
import 'package:fluo/l10n/fluo_localizations.dart';
import 'package:fluo/theme.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const ExampleApp());
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: const [
// Important: add this one
FluoLocalizations.delegate,
// ...other delegates...
],
home: FluoOnboarding(
apiKey: 'your-api-key',
onUserReady: (fluo) {
// Here, your user is onboarded, so do your own things!
// When you need to sign the user out, you can use the
// fluo.clearSession() method. It's async so you can decide
// to use await depending on your use case.
fluo.clearSession();
},
onInitError: (error) {
// Optional - Handle network or server error
// for example, you could decide to show a toast or dialog
}
introBuilder: (context, initializing, bottomContainerHeight) {
// Optional - Present your app on the connection screen
// use 'initializing' if you want to show a loading indicator
// use 'bottomContainerHeight' if you need to position content above the buttons
},
theme: FluoTheme(
// Optional - Customize the look & feel
primaryColor: Colors.black,
inversePrimaryColor: Colors.white,
// ...lots more to customize...
),
),
);
}
}
- Open the dashboard and select the Backend tab
- Click "Set up your backend now" and select "Firebase"
Once complete, when users are onboarded, Fluo securely forwards their information to (1) the Firebase Authentication service and (2) a users
table created automatically in the Firestore Database. As such, make sure the Firestore Database is initialized.
Back to your app code, to initialize correctly the Firebase session, use the fluo.firebaseToken
as below:
FluoOnboarding(
// ...other properties...
onUserReady: (fluo) async {
// 1. Initialize the Firebase client somewhere in your code
// 2. Use 'signInWithCustomToken' as below:
await FirebaseAuth.instance.signInWithCustomToken(fluo.firebaseToken!);
},
)
- Open the dashboard and select the Backend tab
- Click "Set up your backend now" and select "Supabase"
Once complete, when users are onboarded, Fluo securely forwards their information to (1) the Supabase Authentication service and (2) a users
table that you will create as part of the Supabase setup in the Fluo dashboard (don't worry, it's a simple copy-paste).
Back to your app code, to initialize correctly the Supabase session, use the fluo.supabaseSession
as below:
FluoOnboarding(
// ...other properties...
onUserReady: (fluo) async {
// 1. Initialize the Supabase client somewhere in your code
// 2. Use 'recoverSession' as below:
await Supabase.instance.client.auth.recoverSession(fluo.supabaseSession!);
},
)
Pass a FluoTheme
to the FluoOnboarding
component:
FluoOnboarding(
// ...other properties...
theme: FluoTheme(
// Required
primaryColor: Colors.black,
inversePrimaryColor: Colors.white,
// Optional
screenPadding: null,
connectButtonStyle: null,
connectButtonTextStyle: null,
legalTextStyle: null,
legalTextPadding: null,
modalTitleTextStyle: null,
titleStyle: null,
inputDecoration: null,
inputTextStyle: null,
inputErrorStyle: null,
inputTextAlignVertical: null,
nextButtonStyle: null,
nextButtonProgressIndicatorSize: null,
nextButtonProgressIndicatorColor: null,
nextButtonProgressIndicatorStrokeWidth: null,
codeInputThemeDefault: null,
codeInputThemeFocused: null,
codeInputThemeSubmitted: null,
codeInputThemeFollowing: null,
codeInputThemeDisabled: null,
codeInputThemeError: null,
),
)
Note: If you have questions or need
FluoTheme
to be extended, please do not hesitate to contact me at jordan @ fluo.dev