All projects

Case study · 2026

TodoTrip

A mobile app for organising a group trip. Each trip holds the itinerary, the tasks, the map and the expenses, and the app works out who owes what to whom.

Type
Mobile app
Role
On my own: app and backend
Stack
Flutter, FastAPI, PostgreSQL
Tests
16 backend test files, 21 app test files

It's not on the app stores: it runs locally with Docker and Flutter.

A short walkthrough recorded with sample data. TodoTrip isn't on any app store and has no hosted server.
Music: Background Music by ikoliks_aj (Pixabay)

What it is

It came from a holiday with friends: the plan was split across three chats, one of us had paid for the hostel and another for the dinners, and we settled up a month later, from memory.

In TodoTrip you join a trip with an invite code. From then on you see everything about that trip and nothing else.

What you can do

  • A day-by-day itinerary
  • Tasks with a deadline and an owner, plus checklists
  • Expenses split in equal or different shares
  • A map with saved places and, if people choose to, where they are
  • Five languages and eight accent colours

How it works

The list of trips in TodoTrip

The trip list

Each trip shows its dates, who is going and where it stands: which day of the trip it is, how many days are left, or what you owe in red if you have an open debt.

The itinerary of a trip, day by day

The itinerary

Events are grouped by day. Only the next event is highlighted, with how long until it starts, so it's clear what happens next.

The expenses of a trip

The expenses

At the top you see what you owe and the trip total, and below that every expense with who paid and your share. Shares can be different: if you weren't at dinner, you don't pay for it. A debt isn't shown by red alone but also in words.

Tasks of a trip with owners, completed ones grouped

Tasks and lists

Each task has a deadline and the people responsible. Completed tasks go into a group you can collapse, so only what's left stays in view. Next to them are lists, for things to buy or to bring.

Technical choices

Money is stored in cents

What I did

Amounts are whole numbers of cents, and balances are recalculated every time from the expenses and repayments.

What I ruled out

Floating point numbers and a balance stored in a table. Floating point picks up rounding errors after a few splits, and a stored balance sooner or later stops matching the expenses.

Real-time updates usually carry no data

What I did

When something changes, the server only says that it changed, and the app reloads the data the usual way. If the real-time connection drops, the app keeps working and reloads when you switch screens. The exception is live location: it's two coordinates that change every 20 seconds, so they travel directly over the connection.

What I ruled out

Sending the new data inside the update: the phone would have to merge two versions and handle conflicts.

You can't leave a trip until your balance is zero

What I did

Leaving is blocked until your balance is zero. Closing an account clears the user's profile details but keeps the row for accounting references, so past expenses still add up. Historical user-written content is not rewritten.

What I ruled out

Deleting the person and their shares: everyone else's balances would change.

What it doesn't do

  • It isn't published on any app store and there's no hosted server.
  • The backend runs as a single process, because real-time updates are kept in memory.
  • The translations haven't been checked by native speakers yet.
  • The map uses OpenStreetMap's public servers.