- 2
- platforms from one codebase, iOS and Android
- 16
- tables in SQLite on the phone, synced
- 58
- REST endpoints behind them
- 835
- automated tests, app and API
How it started
It started as a real need at Iglesia Jesucristo Mi Esperanza in Sunchales. I looked for something practical for the reality of a worship team and did not find it, so I decided to build it, and to build it so that churches across Latin America could use it too. It is also my final project for the Systems Engineering degree at UTN.
The problem
A church music team runs on information nobody owns. The song list is a folder of PDFs, the key each singer needs is in someone's head, the setlist for Sunday is a WhatsApp message, and who is playing next week is a different WhatsApp message. It works until the person holding it all is away, and then every rehearsal starts from zero.
The approach
A mobile app that holds the song library with chords, key and tempo, lets leaders build setlists for services and rehearsals, and schedules musicians with attendance tracking. Built with Iglesia Jesucristo Mi Esperanza in Sunchales, Argentina, which is the reason it solves the problems teams actually have instead of the ones a product manager would guess at.
Offline is the normal case, not the edge case
Church basements and rehearsal rooms have bad signal. Treating offline as an error state would have made the app useless exactly where it gets used, so it is offline-first: everything works with no connection and syncs when one comes back. Records get their UUIDs on the device, which is what lets two people edit the same setlist on separate phones without a server handing out ids.
Local database, not a cache
SQLite on the device holds the real data rather than a copy of what the server said last. That distinction decides everything downstream: what happens on a conflict, what the user sees while a sync is pending, and whether a write can be lost. A cache you can throw away; a source of truth you have to reconcile.
Built to be handed over
React Native with Expo on the front, FastAPI with async SQLAlchemy and Postgres on the back, TypeScript in strict mode throughout. The stack is deliberately boring: this is a product a volunteer team has to keep running, and the interesting part should be the sync model, not the tooling.
On screen · tap to enlarge
Try it here
The key control from the player, working: change the key and every chord follows, with the sharps or flats the new key calls for.
GAmazing G7grace, how Csweet the Gsound
that Gsaved a Emwretch like Dme.
I once was Glost, but G7now am Cfound,
was Gblind, but Dnow I Gsee.
What's next
Since July 2026 the app is in the hands of real musicians at the church, and the first adjustments come from that use: what actually gets played on a Sunday, not what a backlog says. The public launch, on iOS and Android, is estimated for January 2027. Until then, sonli.app takes an email and lets you know when it is ready.
- Oct 2025Development starts
- Jul 2026· nowTesting with real musicians at the church
- Jan 2027 · estimatedPublic launch on iOS and Android
Stack
- React Native
- TypeScript
- Offline Sync
- REST API
- PostgreSQL
