Case study 01
Snackless
A Flutter wellness app delivering a 30-day audio coaching programme with day-gated content, resumable background playback, and offline-first daily tracking. In beta on TestFlight and Google Play.
A single unlock policy in the domain layer
ProgrammeUnlockPolicy is pure Dart with no Flutter or I/O dependencies. It resolves the highest unlocked day as max(currentDay, highestCompleted + 1), clamped to the programme length, so time-based progression and completion-based progression cannot disagree. Because it is a pure function it is unit tested directly, and every screen asks the same object rather than reimplementing the rule.
BLoC with hydrated state for resumability
State lives in flutter_bloc, with hydrated_bloc persisting the blocs that matter — programme progress, navigation, completion settings — to disk automatically. Reopening the app restores position without a bespoke save/restore path, and the persistence concern stays out of the UI entirely.

The daily loop. Left: the 30-day programme, with completed days checked and the next unlocked. Right: a day's session — audio coaching with resumable playback, a notes field, and the food log.


