Flutter Widgets
Complete reference for Flutter InstantDB reactive widgets
Flutter InstantDB provides a set of reactive widgets that automatically update when data changes. These widgets integrate seamlessly with Flutter's widget tree and provide optimized performance.
Core Widgets
InstantProvider
Provides the InstantDB instance to the widget tree using Flutter's InheritedWidget pattern. This should typically wrap your entire app.
class InstantProvider extends InheritedWidget {
const InstantProvider({
super.key,
required this.db,
required super.child,
});
final InstantDB db;
static InstantDB of(BuildContext context) {
// Returns the InstantDB instance
}
}Parameters:
db(InstantDB): The database instance to providechild(Widget): The child widget tree
Example:
void main() async {
final db = await InstantDB.init(appId: 'your-app-id');
runApp(InstantProvider(db: db, child: MyApp()));
}Watch
Part of the signals_flutter library (re-exported by flutter_instantdb). This widget rebuilds whenever any signal accessed inside its builder function changes value.
class Watch extends StatelessWidget {
const Watch(this.builder, {super.key});
final Widget Function(BuildContext context) builder;
}Example:
Watch((context) {
final db = InstantProvider.of(context);
final isOnline = db.isOnline.value; // Accessing .value creates a dependency
return Text(isOnline ? 'Connected' : 'Disconnected');
});Query Widgets
InstantBuilder
The primary widget for building UI based on InstaQL queries. It handles loading and error states automatically.
class InstantBuilder extends StatelessWidget {
const InstantBuilder({
required this.query,
required this.builder,
this.errorBuilder,
this.loadingBuilder,
});
}Properties:
query(Map<String, dynamic>): The InstaQL querybuilder(Widget Function(BuildContext, Map<String, dynamic>)): Called when data is availableloadingBuilder(Widget Function(BuildContext)?): Optional custom loading UIerrorBuilder(Widget Function(BuildContext, String)?): Optional custom error UI
Example:
InstantBuilder(
query: {'goals': {}},
builder: (context, data) {
final goals = data['goals'] as List;
return ListView(children: [ ... ]);
},
)InstantBuilderTyped<T>
A generic version of InstantBuilder that includes a transformer function to convert raw map data into your own model classes.
Example:
InstantBuilderTyped<List<Todo>>(
query: {'todos': {}},
transformer: (data) => (data['todos'] as List)
.map((json) => Todo.fromJson(json))
.toList(),
builder: (context, todos) {
return TodoList(todos: todos);
},
)InstantBuilder.list / InstantBuilder.single
Convenience static methods for common query patterns.
// Fetch a list of entities
InstantBuilder.list(
entityType: 'todos',
where: {'completed': false},
builder: (context, todos) => ...,
)
// Fetch a single entity by ID
InstantBuilder.single(
entityType: 'users',
id: 'user-123',
builder: (context, user) => ...,
)Authentication Widgets
AuthBuilder
Rebuilds when the authentication state changes.
AuthBuilder(
builder: (context, user) {
if (user == null) return Text('Not logged in');
return Text('Logged in as ${user.email}');
},
)AuthGuard
A higher-level widget that shows a child if the user is authenticated, or a fallback (or loginBuilder) if they are not.
AuthGuard(
fallback: LoadingScreen(),
loginBuilder: (context) => LoginScreen(),
child: DashboardScreen(),
)OAuthButton
A drop-in OAuth sign-in button. Builds an authorization URL (PKCE on by default) and hands the OAuthFlow to onLaunch; your app opens it and calls db.auth.exchangeCodeForToken. Does not bundle url_launcher.
OAuthButton(
provider: OAuthProvider.google, // default label/color/icon
clientName: 'google', // OAuth client from the dashboard
redirectUri: 'myapp://oauth',
onLaunch: (flow) async {
final result = await FlutterWebAuth2.authenticate(
url: flow.url, callbackUrlScheme: 'myapp');
final code = Uri.parse(result).queryParameters['code']!;
await db.auth.exchangeCodeForToken(
code: code, codeVerifier: flow.codeVerifier);
},
)OAuthProvider values: google, apple, github, linkedin, clerk, firebase. Override the preset with label, color, or icon; pass scopes or usePKCE: false as needed. See User Management.
Presence Widgets
Reactive equivalents of InstantDB's React presence hooks. Each joins the room and rebuilds on change. See Presence System.
PresenceBuilder
Equivalent of usePresence. Rebuilds on peer presence changes.
PresenceBuilder(
roomId: 'doc-42',
initialPresence: {'name': 'Alice'},
builder: (context, room, peers) => Text('${peers.length} online'),
)TopicListener
Equivalent of useTopicEffect. Side-effect widget; renders child.
TopicListener(
roomId: 'doc-42',
topic: 'emoji',
onEvent: (data) => _showFloatingEmoji(data['emoji']),
child: const Editor(),
)TypingIndicatorBuilder
Rebuilds with the current typing peers.
TypingIndicatorBuilder(
roomId: 'doc-42',
builder: (context, typing) =>
typing.isEmpty ? const SizedBox() : Text('${typing.length} typing…'),
)ReactionsBuilder
Rebuilds with the live list of reactions.
ReactionsBuilder(
roomId: 'doc-42',
builder: (context, reactions) =>
Wrap(children: [for (final r in reactions) Text(r.emoji)]),
)CursorOverlay
Multiplayer cursor layer — Flutter equivalent of <Cursors>.
CursorOverlay(
roomId: 'doc-42',
userName: 'Alice',
userColor: '#E91E63',
child: const Canvas(),
)Connection Widgets
ConnectionStatusBuilder
Provides periodic updates on the database connection status.
ConnectionStatusBuilder(
builder: (context, isOnline) {
return Icon(
isOnline ? Icons.cloud_done : Icons.cloud_off,
color: isOnline ? Colors.green : Colors.red,
);
},
)State Management Hooks
useInstantQuery
A function that returns a Signal<QueryResult> for a given query. Useful inside StatefulWidget or other places where you want to manage the signal lifecycle yourself.
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
late Signal<QueryResult> query;
@override
void didChangeDependencies() {
super.didChangeDependencies();
query = useInstantQuery(context, {'messages': {}});
}
@override
Widget build(BuildContext context) {
return Watch((context) {
final result = query.value;
// ... build UI
});
}
}