firewatch
Lightweight Firestore repositories for Flutter.
- 🔁 Auth-reactive: attach/detach on UID changes via any
ValueListenable<String?> - ⚡ Instant UI: primes from local cache; then streams live updates
- 🪶 Small surface area: single-doc + collection repos
- 📜 Live window pagination: grow with
loadMore(), reset viaresetPages() - 🧩 No auth lock-in: bring your own auth listenable
Install
dependencies:
firewatch:
Quick start
Firewatch repositories are built to work seamlessly with watch_it.
Here’s the minimal flow: Model → Repository → UI.
1. Define your model
Firestore-backed models must implement JsonModel so Firewatch can inject the
document ID.
class UserProfile implements JsonModel {
@override
final String id;
final String name;
UserProfile({required this.id, required this.name});
factory UserProfile.fromJson(Map<String, dynamic> json) => UserProfile(
id: json['id'] as String,
name: json['name'] as String? ?? 'Anonymous',
);
@override
Map<String, dynamic> toJson() => {'name': name};
}
2. Create your repositories
Repositories bind models to Firestore. Provide authUid
(a ValueListenable<String?>) so Firewatch knows which document/collection to
read.
final authUid = ValueNotifier<String?>(null); // wire this to your auth layer
class UserProfileRepository extends FirestoreDocRepository<UserProfile> {
UserProfileRepository()
: super(
fromJson: UserProfile.fromJson,
docRefBuilder: (fs, uid) => fs.doc('users/$uid'),
authUid: authUid,
);
}
class FriendsRepository extends FirestoreCollectionRepository<UserProfile> {
FriendsRepository()
: super(
fromJson: UserProfile.fromJson,
colRefBuilder: (fs, uid) => fs.collection('users/$uid/friends'),
authUid: authUid,
);
}
3. Consume in the UI with watch_it
Because repositories are ValueNotifiers, you can watch them directly in your widgets.
class ProfileCard extends StatelessWidget {
const ProfileCard({super.key});
@override
Widget build(BuildContext context) {
final profile = watchIt<UserProfileRepository>().value;
final friends = watchIt<FriendsRepository>().value;
if (profile == null) {
return const Center(child: CircularProgressIndicator());
}
return Card(
child: ListTile(
title: Text('User: ${profile.name}'),
subtitle: Text('Friends: ${friends.length}'),
),
);
}
}
👉 For a full runnable demo (with auth wiring and fake Firestore), check out the example/ app in this repo.
Bring your own Auth
Firewatch accepts any ValueListenable<String?> that yields the current user UID. Update it on sign-in/out and the repos will re-attach.
authUid.value = 'abc123'; // sign in
authUid.value = null; // sign out
Commands API
Both repos expose command_it async
commands:
profileRepo.write(UserProfile(id: 'abc123', displayName: 'Marty'));
profileRepo.patch({'bio': 'Hello'});
friendsRepo.add({'displayName': 'Alice'});
friendsRepo.delete(id!);
UI State
isLoading: true while fetching/refreshinghasInitialized(collections): first load completedhasMore(collections): whetherloadMore()can grow the windownotifierFor(docId): get a pre-soakedValueNotifier<T?>for a specific item
Documentation
License
MIT - See LICENSE
Libraries
- firewatch
- Firewatch – opinionated Firestore repositories for responsive UIs.