A habit tracker where broken streaks are repaired with gold.
Every day you keep your habit, the piece rises one coil. Miss a day and it cracks — right where you stopped, exactly as wide as the days you were gone. You trace the crack with your finger and the gold follows. Nothing is deleted, nothing goes back to zero, and repairing is free and always will be.
After sixty days the piece is fired and moves to your museum. No two are alike, because no two people fail the same way.
Built for RevenueCat Shipaton 2026.
flutter pub get
flutter runThe app runs without any keys. Purchases stay inactive and everything else works, which is enough to see the whole product.
To exercise the paywall against a real RevenueCat project:
flutter run --dart-define=RC_ANDROID_KEY=goog_xxx --dart-define=RC_IOS_KEY=appl_xxxIt expects an offering called default and an entitlement called plus.
A habit tracker is hard to review because the interesting states take two
months to reach. Build with VETA_DEBUG and a panel appears that moves the day
the app believes it is; streaks, cracks and repairs all recompute from that.
flutter run --dart-define=VETA_DEBUG=trueFrom there you can seed a sample collection covering every state the interface has to draw — a mature piece with gold seams, one just started, one broken and waiting, and one already fired — and you can open a crack on demand to try the repair ritual.
Everything is drawn procedurally. There is not a single image asset in the app: the ceramic, the glazes, the fractures and the gold are all painted from code, which is why every user's collection is genuinely unique.
lib/domain/ |
The rules. Days, streaks, fractures — no Flutter imports. |
lib/render/ |
The ceramic painter. Surfaces of revolution, banded shading, gold seams. |
lib/data/ |
Local persistence and the RevenueCat wrapper. |
lib/ui/ |
Screens. |
tool/ |
Instruments: contact sheets, blind comparison, pixel measurement. |
A fracture is deterministic: the same piece with the same failure always produces exactly the same crack. That matters more than it sounds — if the scar changed shape on every repaint it would stop being your scar.
flutter testTwo of them are worth pointing at.
test/traiciones_test.dart ("betrayals") holds the guarantees owed to a user
who actually showed up. Every test there describes a way the app could take
progress away from someone who did the work: a daylight-saving change that
opens a crack you did not earn, a flight across twelve time zones, a repaired
break being charged twice, a clock set forward by mistake leaving a permanent
scar, a half-written save destroying the whole collection.
test/sin_agujeros_test.dart paints every shape at six heights over magenta
and walks each row: between the first ceramic pixel and the last there cannot
be a run of background. It exists because a two-pixel seam between the wall and
the rim read as a chip in the lip — a piece damaged for no reason.
MIT. See LICENSE.