Christchurch, NZ ·

← All work

caralune

One platform for running a care business, where the screens decide nothing.

The same list of six made-up people across three made-up centres, seen by four logins. The owner sees all six. A manager sees the four in Centres A and B. A team member sees the two in Centre A. A family sees one row, their own. Every other row is an empty dashed outline.
Drawn for this page in caralune’s colours and type. The centres and people are made up. The dashed rows aren’t hidden on screen: that login never gets them from the database.

Care data is the most sensitive data there is. So no screen gets to decide who sees what, or what has been paid.

I was working with a group of care centres in the UK that ran on a patchwork: one tool for bookings, another for payments, spreadsheets for everything else, and a front desk that spent its mornings approving requests by hand. No generic booking plugin was built for this.

So I built caralune. Bookings, payments, care records, consent and staff sit in one place, with the access and money rules kept on the server. Phones and web pages only show the answer. It started with the group’s own centres, with their old booking data moved across, and the managers run their day on it.

Who sees what

An owner sees the whole group, a manager their own centres, a team member their workspace, and a family only themselves. That rule sits in the database, so there is nothing on screen to get around. Each of the 63 tables has row-level security: the database checks who is asking on every request and hands back only their rows. Changes to care records also go into an audit trail.

Staff can take a card on the iPhone itself. The phone still decides nothing.

A member of staff opens a booking, taps Take payment and holds the customer’s card to the back of the phone. No reader, no extra hardware. It was the part I enjoyed most, and it is where the rule matters most.

A chart of who does what in a card payment. The phone asks, the server sets the amount and the phone shows it. The card is held to the phone and goes to the payment provider, which confirms it to the server. The server marks it paid and the phone shows Paid. The phone never picks an amount and can never mark anything paid.
Drawn for this page. The amount is made up.

Trying to break it

Before real money touched it, I had the whole payment flow put through an adversarial review, where the only job is to find what’s wrong. It found 36 things. Two were serious: a charged card shown as declined, and a Cancel button that cancelled nothing. Both were fixed before launch.

A tablet showing a day at a sample centre: the schedule on the left, and on the right two requests waiting for approval above a lime Approve 4 button.
An illustration from caralune’s home page, not a screenshot of the staff app. I changed its sample names and removed its takings figure.

The staff app is built for the floor, for use between rooms. Managers approve a booking with a swipe, see the day’s schedule, handle requests and send a receipt or a refund, all from a phone.

One form, any centre. Only the settings change.

The booking form can sit on a centre’s own website. Its name, colours and services come from the server, so the two below are the same form.

The booking page for Hebburn Day Care with teal accents and four services: Hydropool, Sensory Room, Immersive Room and Rebound Therapy.The same booking page for Inspired Day Care with dark green accents and one service, Hydro Pool.
Two centres’ live booking pages. Drag across to compare.

The family app works the same way. There is one app for every centre: families pick theirs, sign in with a six-digit code, book, reschedule or cancel, and open their invoices. The logo, colours and tabs are all set from the server, so a new centre is a change of setting, not a new build.

Underneath

63
Tables in the database, every one with row-level security.
88
Migrations, the saved steps that change the database over time.
500+
Automated checks across the web app.
2
Native mobile apps, one for staff and one for families, on top of the web app.

A phone doing its own sums

Two bookings once showed amounts owing that the server said were nil. The app had been working out balances itself.

I deleted that code. Now the app only shows what the server says.

More work