local-first capacity planning
Senna
A planning system that treats a week as a budget rather than a list. Work is entered as items with estimates, then placed into capacity blocks; the app measures what was actually completed against what was planned, so the plan and the week can be compared rather than remembered.
It runs on the machine. An Electron shell over a local SQLite database — no account, no remote database, no sync to reconcile. The design constraint was that the tool must work on a laptop with no connection and no server behind it.
It plans to a deliberate 60% floor rather than a 100% target, because a benchmark you keep missing gets abandoned. The remaining capacity absorbs the interruptions that no estimate contains.
Architecture and what it solves
What this solves that off-the-shelf tools leave open
- Commercial planners are built for teams: seats, accounts, a server, and a sync model that reconciles concurrent edits. A single-operator plan needs none of that and pays for all of it — in latency, in subscription, and in who holds the data.
- They model work as tasks with a status. Capacity is not a field, so ‘what fits in this week’ stays a judgement rather than a constraint the tool can enforce.
- They optimise for utilisation. Planning to a 60% floor is the opposite bet: the schedule has to survive contact with a real week, or it gets abandoned and the measurement becomes fiction.
- The measurement is the product: a plan you can hold against the week that actually happened, rather than a schedule that only records intent.
- Local-first shaped the architecture from the first commit — it is not a feature added to a hosted design.