CovalFlow
2026 · Designer and lead developer, built at CovalTech.
Volunteer scheduling for event organisers: profiles, e-signed contracts, automatic reminders, and a shift plan generated by a constraint solver in under 10 seconds.
What I delivered
- A shift plan generated by a constraint solver (OR-Tools CP-SAT) in under 10 seconds
- A self-service app where volunteers declare their own availability
- Re-planning that keeps every assignment already locked in by hand
- Contracts with a real e-signature (self-hosted Documenso), tracked and reminded automatically
- PDF exports: one plan per event, one route sheet per volunteer
- Volunteer profiles shared across organisations, each organisation's data kept isolated
- Settlements: cash and wire amounts owed per volunteer, per event
In numbers
- to plan 100 volunteers across 400 shifts
- < 10 s
- associations using it live
- 3
- contracts signed from a phone by one association
- 68
- automated tests on the solver
- 48

Context
Event organisers running on volunteers, mostly associations covering events of a few hundred to a few thousand attendees, were scheduling shifts by hand in a spreadsheet and chasing signatures over email and PDF attachments: availability, skills and rest rules tracked in separate documents that fell out of sync the moment someone changed their mind. I felt this problem directly, coordinating volunteers for a two-day event where a clock change in the middle of the night undid most of a finished plan. Moving one person off a shift meant moving several others around them, and the sheet had to be rebuilt, not patched.
The problem
A feasible schedule has to satisfy every volunteer's availability, skill and rest constraints at once, cover every role an event needs, and a spreadsheet cannot prove any of that. Past a few dozen volunteers, checking it by hand stops being reliable, and a single withdrawal the night before an event can force the whole plan to be rebuilt from nothing.
Constraints
Contracts needed a real signature, not an email attachment nobody chased. A plan already published, sometimes already partly signed, could not be silently overwritten the moment something changed: regenerating it had to keep every assignment already locked in by hand and only rework the rest. And the organisers running this are small associations, so the stack had to stay self-hosted and cheap to operate, not a SaaS bill per seat.
What I built, in detail
Volunteer profiles that follow a person across organisations, since the same volunteer often works with more than one association, behind an org switcher that keeps each organisation's data isolated from the others. Event roles (security, bar, reception) with remuneration set per assignment, a self-service app where volunteers declare their own availability, and a planning screen backed by a Python service (FastAPI, Google OR-Tools CP-SAT, covered by 48 tests) that turns availability, skill and rest rules into a feasible shift plan, with a tooltip explaining why any volunteer was left unassigned. A published plan survives a regeneration: assignments already locked in by hand stay locked in, only the rest gets recomputed, and the whole thing exports as a PDF, one view for the event and one route sheet per volunteer. Contracts, tied to an event or standalone, get a PDF and a real signature through a self-hosted Documenso instance, tracked from generated to sent to signed, with automatic reminders for the ones still waiting. A settlements module closes the loop: cash and wire amounts owed per volunteer, per event.
Decisions
- A constraint solver instead of a rule engine
- OR-Tools CP-SAT treats availability, skill and rest as hard constraints and proves a feasible plan exists, instead of a best-effort heuristic that can silently leave a shift uncovered.
- Impact A plan for 100 volunteers and 400 shifts in under 10 seconds, with every constraint checked.
- Multi-tenant from the first migration
- Every table carries an organisation id, and a volunteer working with two associations switches between them without either one seeing the other's data. That mattered from the start: CovalFlow runs several associations on the same instance today.
- Impact 3 associations run on the same instance, and none of them sees another's data.
- Self-hosted e-signature
- Documenso, self-hosted, gives every organisation a real signed contract without a recurring per-seat SaaS bill, which matters for a volunteer-run association.
- Impact One association had 68 contracts signed from a phone, with no per-seat subscription.
- AI-assisted solver, human-reviewed
- Python is not a language I write daily. I designed the OR-Tools model and the module boundaries, then reviewed every line an AI agent wrote before it shipped.
- Impact The solver shipped covered by 48 tests.
Result
The solver plans 100 volunteers across 400 shifts in under 10 seconds, and CovalFlow runs today for 3 associations. Two events into using it for real, one association had managed 80 volunteers and signed 68 contracts from a phone, without printing a single page. The surprise was not the time saved on the plan itself, it was not spending evenings chasing people for a signature anymore.
100 volunteers and 400 shifts planned in under 10 seconds, live for 3 associations.
Stack
- React
- TypeScript
- Node.js
- PostgreSQL
- Python (OR-Tools CP-SAT)
- FastAPI
- Docker