offline_first_sync

Offline-first sync layer for Flutter apps. Wraps your remote repository (e.g., REST, Firestore, etc.) with a local SharedPreferences store and a small sync engine.

  • Local-first UX: writes go to local immediately, background sync hydrates from remote
  • Pluggable: implement OfsRepository for your backend, or use your existing service with a thin adapter
  • Minimal types: OfsTask, OfsSettings, and Weekday

Install

Add to your pubspec.yaml:

dependencies:
  offline_first_sync: ^0.1.0

Quick start

  1. Implement OfsRepository for your remote (example: in-memory or REST):
class MyRemoteAdapter implements OfsRepository {
  // Implement all OfsRepository methods for your backend
}
  1. Use the provided SharedPreferences local store:
final local = SharedPrefsLocalStore();
final remote = MyRemoteAdapter();
final repo = SyncRepository(remote: remote, local: local);
  1. Read from repo (local-first) and call write methods; the sync engine will hydrate from remote in the background.

API overview

  • OfsRepository: repository contract used by SyncRepository (implement for your backend)
  • OfsLocalStore: extends OfsRepository with hydrate and replaceSettings
  • SharedPrefsLocalStore: reference implementation of OfsLocalStore using SharedPreferences
  • SyncRepository: combines local and remote stores for offline-first sync

Usage snippet

final repo = SyncRepository(
  remote: MyRemoteAdapter(),
  local: SharedPrefsLocalStore(),
);

// Add a task
await repo.addTask(OfsTask(
  id: '1',
  title: 'Buy milk',
  completed: false,
  weekday: Weekday.monday,
  time: TimeOfDay(hour: 9, minute: 0),
));

// Listen for syncing status
repo.isSyncingNotifier.addListener(() {
  print('Syncing: ${repo.isSyncingNotifier.value}');
});

Backend-agnostic

This package does not include Firebase or other backend dependencies. You must implement your own adapter for your backend (REST, GraphQL, etc.) by implementing OfsRepository.

Time fields use Flutter's TimeOfDay, so Flutter SDK is required.

License

MIT