-
-
The room is the interface: Milo's bowls, fountain and litter box show at a glance what has been logged.
-
Logging takes a gesture: drag the food bag to the bowl, then confirm. A tap alone never logs anything.
-
Once confirmed, the cat says it in its own voice. It only talks about what has been logged, never about what it can't know.
-
The Record keeps who did what and when. Jane and Tommy share Milo, and every entry carries the caregiver's name.
-
The shop is drawn in the same paper: coins buy furniture, decorations, moves and scenes for the room.
-
In the Studio you paint your own cat with a watercolour brush over the cream base. This is Milo.
-
A closed palette, coat references and a stroke that stays inside the silhouette keep every painted cat in the same style.
-
The album: every movement is two sheets that alternate like a paper puppet, every pose is one. Paint each frame to match your cat.
-
After sign-up, a welcome box arrives and unpacks the care objects one by one onto the shelves and the floor.
-
Medication works the same way: take the bottle from the shelf to the cat, then choose Given, Not given or Not now.
-
The Pro offer is a paper sheet with the cream cats moving inside it, yearly above monthly. RevenueCat handles the purchase.
-
Caring together: invite someone with a private code and choose which pets they see, as a participant or a cat sitter.
-
Styles change the paper of the whole app at once: eight themes, light or night mode, paper finish and watercolour.
-
The OneSignal medication Journey: it enters on an app event, waits until the dose is logged and sends three reminders, each with its goal
-
Icon
Inspiration
I have three cats. Every time I travel, the same thing happens: I spend the trip wondering whether anyone has fed them. So I text the person looking after them: “Did you fill the water?” “Did you clean the litter box?” And they forget to answer, or they forget to do it, and I have no way of knowing which...
I had looked for apps to solve this before. They were all task lists. Checkboxes, reminders... I never understood them and I never kept using them.
I gave up on the Shipaton at first. I had two apps in development and neither of them was published. The deadline required a live app, and a month was clearly not enough. But the ad kept following me around Instagram until I gave in and read it properly. Then I thought: fine, I'll build something small and fast. But small and fast does not exist for me. That is my worst habit as a builder, and this project is the proof.
What it does
Catitin turns pet care into a room you read. If the bowl is full, someone already fed them; if the fountain has water, there is water. If the litter box is dirty, nobody has recorded cleaning it yet. You open the app, you look, and you know. No reading required. Logging care is a gesture, not a form: you drag the can to the plate and confirm. Half game, half real record. Everyone in the house sees who did what and when, so nobody has to ask and nobody does it twice.
The cat in the room is yours. In the Studio you paint it over a cream base with a watercolour brush and a closed palette, one sheet at a time, and every pose and every movement can be painted. It is still my drawing; it just wears your cat's markings.
Care is shared by invitation. You create a code, the other person enters it, and they see the same room. When they log a care, the cat tells everyone else in its own voice: "Tommy gave me dry food!" Nobody is told about their own care. The Log keeps who did what and when.
Medication is where a missed message matters most, so Catitin treats it differently. A dose has its time, and if nobody logs it, the other caregivers hear about it. The app never claims the medicine was given; it only knows whether someone logged it. Logging it is the same gesture as everything else: drag the medication from the shelf to the cat. On the iPhone, the room also reaches the lock screen as a Live Activity, so someone with a silenced phone still knows, without being interrupted. How I built that with OneSignal has its own section below.
Around the room: a Log, a vet calendar with vaccinations, notes with photos, several pets with a room each and a shared room where feeding three cats is one gesture instead of three, and a shop where coins buy objects for the room. Catitin Pro unlocks the parts that make care genuinely shared. The app speaks English, Spanish and French.
How I built it
I drew the first cat by hand. Everything after that had to stay faithful to that drawing, which turned out to be the hardest constraint of the whole project, and the one I refused to drop.
I used AI to generate the rest of the assets from my own original design, so I was extending my drawing rather than borrowing anyone else's style. I wanted people to upload a photo and get their own cat's markings back in my style.
That was impossible: the models were too inconsistent to hold the style, and I would have needed to train one. Without that, the app would have filled up with things that looked almost like my work. So I made the coats myself instead, plus a sphynx.
Then I wanted the cat to move. I spent almost a week on it. I tried Godot and Unity.
Rigs deformed the drawing. I had no time to build and paint 3D models and no idea how to do it well. And the deeper I went into a game engine, the harder everything else got: the shared database, the notifications, the near-real-time sync between phones... So I generated video, extracted every frame, and hand-picked the ones that simulated each movement. It worked. It also weighed 22 frames per movement, times 15 movements, times 66 coats. Unsustainable.
Then I remembered South Park. And Paper Mario. And the paper theatres I loved as a child. Cutout animation. Two frames instead of twenty-two. It isn't fluid, and that is exactly the point: the stiffness is what tells you it is paper. The cat floats, alternates between two drawings, and reads as a hand-cut puppet rather than a cheap animation.
That fixed the weight but not the arithmetic: two frames times twenty movements times sixty-six coats was still impossible in two weeks. So I made one cream cat, and built a studio where each person paints their own with a watercolour brush, a closed palette and a canvas tuned until the result is faithful to my original style. That solved personalisation and removed the need for me to paint every coat in every pose.
Then I converted every existing asset to cream by hand in IbisPaint. 52 drawings, one at a time. It was slow and it was worth it. The catalogue ended at 20 movements across 39 drawings and 13 poses, like cut from paper, all in the same hand.
From there it kept growing: care logs, vet calendar, vaccinations, notes, a shop, multiple pets with a room each, and a shared room so that feeding three cats at once is one gesture instead of three.
Supabase became the shared memory of the household, while OneSignal handles the part that another phone cannot know on its own. When one caregiver records an action, the right person can be notified without alerting the person who just did it. Medication notifications distinguish between a scheduled dose and one that has not been recorded, because the app must never pretend to know whether medicine was actually administered.
RevenueCat powers Catitin Pro and its credit economy. Pro unlocks the parts that make care genuinely shared, while credits let people expand their paper home. I designed the subscription and store experience to remain inside Catitin's visual world instead of dropping the person into a generic commercial interface.
Behind the paper there is an ordinary stack doing unusual work. The app is React Native with Expo, and the room, the two-drawing cat and the watercolour brush are all drawn with Skia on one canvas. Supabase is the household's memory: each person only sees the pets they care for, and the server keeps the clock for medication and shared activity. RevenueCat runs Pro and the coin packs on both stores, and a webhook keeps each account's access in sync. OneSignal carries what one phone cannot know about another, including the Live Activity on the iPhone lock screen. Sentry and PostHog tell me what breaks and what people actually use. EAS builds the apps in the cloud and ships over-the-air updates, which is how a fix reaches phones the same day.
For the art, I drew in IbisPaint and Fresco.
The Android testers shaped the app during the closed test. Through a feedback board and messages they found what I could not see on my own: small bugs, translations that were wrong, and moments where the app glitched, restarted or flickered. Everything they told me went into fixes and polish over those two weeks.
Challenges I ran into
The real challenge was not technical. It was that I insisted on my own visual language instead of using pixel art, which would have been far easier to animate. Every problem in this project traces back to that decision, and I would make it again. The rest: animating a hand-drawn 2D character without deforming it; carrying an illustrated identity across dozens of poses; and rebuilding the visual model halfway through, once the studio existed, while the app was already using the old cat.
And then there was everything else. I started on the evening of 22 August, when I finally read the Shipaton ad properly, and I don't have a Mac. I developed on Windows through WSL, compiled the iOS builds in the cloud, and tested on devices including a Samsung tablet, an iPhone XS Max and a second-hand iPhone 12.
The code was written with AI coding agents. The cat, the design, the UX and the UI are mine. Agents are only as good as the method around them, so I kept an error log: what I saw, which change caused it, why, how it was fixed and the proof. By the end it had almost 200 entries, and two rules became part of the method. If something used to work, find the change that broke it instead of guessing. And a fix is never allowed to contradict a decision I already made.
Green tests meant nothing on their own. At the end of August, 181 tests passed while the room was completely broken and the app crashed on launch, because none of them loaded the room. Later, two attempts at making the app work offline broke the canvas, the appointments, the notes and the pets on the Samsung while more than a thousand tests stayed green, so I went back to the first build with over-the-air updates and left offline mode for after launch. From then on, a visible change only counted as done once it had been checked on a real device. The suite grew to about 1,700 tests, and I still looked at the screen.
Paper is heavy. Moving the images to WebP took the scene catalogue from 41 MB to 1.4 MB, and in a development build on the Samsung memory still jumped from 769 MB to 1.82 GB the moment the room loaded, so several animations now load only when they are needed, from smaller copies. Then the Studio made it heavy again: a painted sheet is a stack of watercolour strokes, on the Galaxy Tab composing one cost about 40 ms per stroke, and a painted cat slid across the floor instead of walking. Now each painted sheet is flattened into a single image outside the canvas, and the room just draws it.
The hardest bugs lived between two people. For a while the app saved a care, but after a reload every object in the room looked undone again, because the room only kept its state in memory. The other caregiver's phone only updated when a notification arrived or they opened the app again, so without notifications the log could stay frozen. A temporary caregiver could delete someone else's care on their own phone while the server still kept it, so they saw an empty bowl while the owner saw it full. And reading the history got slower with every care logged anywhere in Catitin, because access was checked row by row across every account; one change in how access is calculated took a read from 3.4 seconds to 0.18.
One bug touched medication. The date and time wheel saved a value nobody had chosen while the screen showed the right one, and four doses ended up at midnight. It came from a change that removed a 650 ms delay on Android and, with it, the check that the person had actually moved the wheel. Now only a real drag chooses a value.
The first iOS build reached TestFlight on 16 September, two weeks before the deadline, with its own list. The paper lines and buttons came back blank when you returned to a tab, because iOS destroys hidden views and Skia loses the drawing; the fix went into React Native and Skia themselves, so that iOS keeps hidden views the way Android does. Objects lagged behind my finger and switching screens took three or four seconds, while the first run in a simulator showed none of it. Without a Mac I worked with remote simulators and diagnostic updates, and part of that slowness still has no proven cause. By then Android was already in my testers' hands, so every iPhone fix had to reach iPhones without touching Android. On 19 September I went back to one codebase, with platform folders and conditions, and a separate over-the-air update for each platform.
The stores were a project of their own. A new personal Google Play account needs at least twelve testers enrolled for fourteen days in a row, and then a review, before it can publish, and the Shipaton rules ask for an app the judges can download, not a closed test. On 8 September it was clear Android would not make it by the 30th, so the App Store became the main route and Android kept going; I did Apple's paperwork in one night. Apple's first answer was a rejection: as a new developer account, they wanted a video on a physical device with the latest iOS and six written answers, and Catitin had no recorded runs on iOS 27 yet. I fixed what the reviewer would see first, compiled a new build, recorded the video on iOS 27 and resubmitted. It was approved on 26 September, in 148 territories but not in the 27 EU countries, where Apple's trader verification was still pending.
The first update was rejected too. The reviewer, on an iPad, signed in and kept landing back on the login screen. The cause was not the iPad: a brand-new account that came in through "I already have an account" had no cat, and the app sent it back to the start. The bug had been there since 5 September, and a fix on the 16th had written it down as expected behaviour.
There are no download figures to show yet: the app came out on 26 September, and I live in Spain, where it is not available because Apple has not yet approved the EU trader verification. The project records hold the rest, almost 1,900 notes on problems, attempts and fixes.
Accomplishments that I'm proud of
Above all, this: my first app, published in 35 days, with a cat I drew by hand, every asset grown from that drawing, and a visual identity that is mine and nobody else's. Catitin was live on the App Store on 26 September, and it went out with its two Pro subscriptions and four coin packs approved alongside it. Apple approved a second version three days later, on the 29th, as a bug-fix submission, and the fix went out over the air that same afternoon.
On Android, the closed test ran its fourteen days with more than twelve testers, and by 28 September they had logged 389 cares. Catitin speaks three languages, with 1,556 text strings in each. And I never traded the cat for something easier to animate.
What I learned
That I overbuild, and that constraints are the only thing that stops me. Every good decision in Catitin came from hitting a wall: cutout animation came from the frames being too heavy, and the painting studio came from not being able to draw sixty-six coats in every pose.
That a green test suite is not a working app, and the only real check for anything visual is a phone in my hand. That if something used to work, the answer is in the change that broke it, not in a new theory. That a second opinion is only useful if it gets the raw facts and not my conclusion. And that publishing is a project of its own: two stores, twelve testers for fourteen days, a video for Apple and a rejection I did not see coming.
I also shipped my first app.
What's next for Catitin
Dogs, of course. More rooms, more movements, more poses...
Before that, the unglamorous part: Catitin in the EU as soon as Apple's trader verification clears, Android moving from the closed test to production, and the offline mode I took out before launch.
Built With
- adobe
- cloudflare
- eas
- expo.io
- ibispaint
- limrun
- onesignal
- postgresql
- posthog
- react-native
- resend
- revenuecat
- sentry
- skia
- supabase
- swift
- typescript
Log in or sign up for Devpost to join the conversation.