Six Kittens Should Not Be Six Rows

· Pavel · release

littersrescuereleaseoffline

A mother cat turns up with five kittens. You start doing the responsible thing and putting them into the app, and somewhere around the third profile you realize what you have built: six rows that look almost identical, named Kitten 1 through Kitten 5, with the same birthday, the same deworming date, and the same photo taken from slightly different angles.

The app was technically correct. Five kittens are five animals. But nobody who has ever fostered a litter thinks about them that way for the first eight weeks. They are one situation with five sets of paws in it.

v1.19.0 makes litters a real concept in Meo Mai Moi, and v1.19.1 finishes the parts we got wrong the first time.

What a Litter Does

You can create a litter from the My Pets page, or straight into a group if the animals belong to a shared rescue workspace. The litter gets its own detail page, and in the pet list its members collapse into one card instead of five. You can name it and rename it, which sounds trivial until you are tracking three litters at once and “Litter #2” stops meaning anything.

Litter membership also shows up on the pet payload itself. Without that, nothing outside the app could answer a question as basic as whether two pets are littermates. The API knows now, and so does the MCP connector.

The small one I like most: pet avatars now appear in the habit day dialog. When five kittens share a feeding habit, a list of names is much harder to read than a row of faces.

The Day a Litter Stops Being a Litter

Kittens do not leave together. They leave one at a time, over weeks, to different people, and the ones still with you keep needing weights and vaccinations while the paperwork for the ones who left stays relevant.

So a litter had to survive its own members going away. v1.19.1 keeps litters usable after members are rehomed, and you can split a litter back into individual pets whenever it stops being useful as a group. Splitting is a normal ending, not an error state. At some point five kittens really are five cats with five different lives, and the app should let go at the same time you do.

The Demo Has a Household Now

The public demo used to be a fairly lonely place. It now seeds a whole household plus placement requests that a visitor can actually respond to, so you can walk through a real rehoming flow instead of staring at an empty list and imagining one.

The demo dog formerly known as Suki is now Hazel. No deep reason. Suki is a real dog and it felt strange to keep her in a fixture.

The Bug I Would Rather Not Have Shipped

While working on this, we found something in the offline queue that had been quietly wrong: a replayed write could be dropped from the queue before it was persisted. If the network came back at exactly the wrong moment, your change went into the void without saying anything.

That is the specific failure mode I promised this app would not have. We now persist the replayed write first and drop the queued operation second. Medical records also queue properly after an offline request failure, instead of being lost with the request that carried them.

If you are at a clinic with one bar of signal and you type a weight into your phone, that number needs to exist afterwards. Everything else in the offline story is decoration around that one promise.

Every Dev Deploy Now Runs the Suite

The e2e suite now runs against dev after each deploy and publishes its report, with its own notification. The launch can never fail the deploy, and secrets stay out of the process arguments.

This is unglamorous plumbing, and it exists because I am one person shipping several times a week. A test suite that runs when I remember to run it is a test suite that catches bugs after users do.

Litters were requested by people doing actual foster work with actual kittens. That is usually the sign a feature is worth building.