← All work

FocusReef

A productivity app where 25-minute focus blocks become tokens, and tokens buy fish for an aquarium that only grows if you actually work.

Role
Personal project · Android app
Year
2026
Stack
Kotlin · Android · NAS-hosted database · Time-series data
Status
Shipped App complete; running on sample data until the desk firmware publishes real blocks

Problem

Gamified focus apps rely on you being honest with them. You press start, you press stop, and nothing checks whether you were at the desk in between, so the score only means whatever you decide it means.

The desk already knows. It runs the Pomodoro cadence, it moves at the start and end of a block, and it publishes what happened. Taking the reward from that record instead of from a button is what makes the score worth anything.

Solution

An Android app in the Forest lineage, with the loop moved off the phone:

  • A completed focus block is worth a number of tokens, and tokens buy fish and aquariums. The aquarium ends up being a picture of how much work has accumulated.
  • The blocks are read from a time-series database hosted on a NAS, which the ESP32 controller writes to over MQTT. The app is the frontend of a system it doesn’t control.
  • The split is deliberate: the desk owns what happened and the app owns what it’s worth, so either side can be replaced without touching the other.

Where it stands

The app is finished: the token economy, the shop and the aquarium all work. What it doesn’t have yet is real input, because the desk firmware is still in progress, so for now it runs against sample data.

The art is not final either. Every fish, background and icon in the screenshots above is a placeholder, enough to get the mechanics working and nothing more. The visual design is the last thing I plan to settle.

What’s next

A standalone mode with a built-in timer, for anyone who wants the aquarium without wiring an ESP32 to their desk. The app counts the block itself and feeds the same token economy, which makes FocusReef usable on its own instead of as one half of a system. It also improves the design, because it forces the block source to be an interface rather than an assumption.