Skip to contentWork

Personal

Vacationr

Bookings and shared costs for a family holiday home

Year
2026

I'm building Vacationr for the holiday home my family shares. One calendar holds our own stays, friends' stays and the platform bookings. A ledger keeps track of who owes the house money, and who the house owes. Every payment goes between a member and the house, never between two of us. It's a work in progress, built for one house.

One transfer closes the stay and the firewood together. The names are pseudonyms.

The spreadsheet

The house is a family chalet in the Alps. Six adults share it, and the chalet has one Swiss bank account. Pay for the winter's firewood and you claim it back from that account. Book a week and you pay into it.

Before Vacationr there was a spreadsheet, which I built in March. Two tabs drew the year as a calendar, coloured by who was staying. A script pulled the Airbnb calendar every six hours and flagged any stay that clashed with it in red. A summary tab worked out what each person's nights cost at the season's rate. Whether anyone had actually paid was a column somebody typed in by hand.

It did the arithmetic and none of the deciding. Was the week free? Was the request fine? Had the firewood been paid back? All of that still went through one person, by message.

Nothing off the shelf

I looked for something to buy first. Software for holiday homes is made for renting them out, with a host, guests, nightly rates and a payout. We're not a business, and the people staying are mostly the owners. Tools for shared ownership assume shares, a schedule of weeks per owner and a company in the middle. We have none of those. We're a family with one bank account, a calendar, and a cleaner who should see the broken gutter and nothing about money.

So the roles come from the house. Members book and pay. Admins approve requests and claims, and mark money received. Helpers see maintenance and the house guide, and nothing financial.

The house account

The money follows the bank account. The account is a party in its own right, and whoever looks after it just has a role. Putting one person in charge of the money would fail the first time they paid for something, because they'd owe themselves.

A member is invoiced for their own stays, due seven days after the booking is confirmed. They're paid back for what they spend on the house. Every payment runs between a member and the property.

What the house pays for itself, from insurance to council fees, stays out of everyone's balance. Nobody here holds a share. Splitting those costs between us would turn the app into an accounting system, and that's not the problem the family has.

One transfer

A member settles one balance, what they owe the house minus what it owes them. Say a stay costs CHF 331 and they paid CHF 210 for firewood. They make one transfer of CHF 121. When the house owes more, it pays them instead. The admin marks the transfer received or paid out, and that closes every line it covers. Two transfers would be confusing, however well we explained them.

A member's Overview shows that as a calculation. It leads with the stay, minus the firewood they paid for, which equals the transfer and its due date. An ⓘ beside the total opens the quote behind the figure, line by line.

When a member's lines cancel out, an admin marks CHF 0 received to close them. An invoice their balance already covers is marked covered, not overdue. And when two stays are open at once, the Overview leads with the one due soonest and still shows one transfer.

A member's Overview: the stay at CHF 331, less CHF 210 for firewood they paid for, leaves CHF 121 to transfer by 19 May. The ⓘ beside it is open on the quote: four nights for two adults in summer CHF 57, cleaning CHF 250, tourist tax CHF 24, total CHF 331.
A member's Overview, with the quote behind the total open.

The admin's Overview shows the other side of the same money: what needs a decision, who's overdue, the month's money in and out, and who arrives next.

Traceable numbers

I build the numbers before the screens. Money is whole centimes everywhere, never a floating-point number, which can pick up rounding errors. A member's balance and the breakdown under it read from the same running total, so they can't drift apart. One test checks every figure the designs show. Others generate 500 ledgers, settle each one to zero, and check that shuffling the records leaves every balance unchanged. Claude Code writes the code from my specs. I review it, and these tests are how I trust what it wrote.

Every word a screen shows comes from one function per page that turns the house's records into text. The tests read that function, not the pixels. I also compared the built Ledger and Overview with their Figma exports. For each difference, I wrote down whether the design or the code was right, and why.1

How it looks

The background is off-white and the surfaces are white, like alpine daylight. One deep bottle green is used sparingly, for the thing you're meant to press. Each of the three typefaces has its own job. Host Grotesk is for the wordmark and page titles, and Switzer for everything else you read. Commit Mono is for every figure, date and tag, so a column of money lines up.2

Open items, like a pending request, a stay that's due or an overdue invoice, get a tinted tag. Once something is settled, the tint goes and it becomes a thin outline with the date inside: PAID · 14 MAY, RESOLVED · 14 MAY. That way, what still needs doing stands out from what's done.

A member's Ledger. Open items carry tinted tags: a stay due 19 May, a lawn mower expense pending, a firewood expense approved. An earlier stay that is settled has an outlined tag, Paid · 14 Feb.
Open items are tinted. Settled ones are outlined, with the date.

On a phone, the calendar is a list. Seven columns at 390px leave about 44px a day, so a guest's name shrinks to a letter. The list keeps who's staying readable.

The member Overview at phone width: CHF 121 owed, the stay at CHF 331 less CHF 210 for firewood, to transfer by 19 May, with the next stays below and a tab bar at the bottom.
The Overview on a phone.
The calendar at phone width as a list of May's four bookings, each with the guest's full name, dates, nights and a tag: family, Airbnb or friends.
The calendar, as a list.

Small things

Buttons that move a record along, like Approve or Mark received, are safe to press twice. A second click finds its work already done and changes nothing. That matters on the Maintenance page, where Resolve takes Start's place the moment you press it.

The labels use plain words. An expense shows who it was "Paid by", and a stay that's too short shows the "Minimum stay".

Where it stands

The money model and the Overview are built, merged and tested, with 486 tests as of October. Still to come: booking from the calendar in one step, the settings where the tariff lives, and the last of the phone layouts. It's deployed at vacationr.vercel.app, and the family hasn't used it yet. That's the next step.

  1. The rulings live in the repo as numbered build notes beside the design file's exports, and two architecture decision records describe the money model: the property holds the money, and a member settles one balance. ↩
  2. Host Grotesk is by Element Type, Switzer by Indian Type Foundry, and Commit Mono by Eigil Nikolajsen. The icons are Lucide, with Tabler's Airbnb mark. ↩