Birthday Sleeps
Async Digital Ltd Cardiff, UK
Birthday Sleeps counted the days to the next birthday on one screen. It was finished: five weeks of work, English and Welsh, iPhone and iPad, a test suite that drove every screen. Then the one child it was built for looked at it and moved on. This page is the record of what was built, and of why I now think a designer is still needed.
The engineering was never the part that failed
Everything an engineer can be held to, this app did. It ran. It was fast. It was bilingual on the first build rather than the last. A button and an incoming link reached the same screen down the same path, one test drove the app end to end through a real browser, and its data never left the phone. If you handed the repository to a reviewer and asked whether the work was competent, the answer would be yes.
None of that is what decides whether a seven-year-old opens an app twice.
The thing I could not supply, and the thing an AI design agent could not supply either, was the judgment of someone who has watched a lot of children use a lot of apps and knows what holds their attention in the first four seconds. That is a specialism. I treated it as a gap I could close with care and iteration. It is not.
A brief is what an AI designer works from. Knowing what a child does with a screen is not something you can put in a brief, because you only learn it by watching children.
One screen, and the number on it
The whole product was a number. The nearest birthday appeared as a large count of sleeps, the rest of the year receded below it in a list, and a button added someone new. Tapping a person opened a ring showing the same count with the date under it. That was the app.
Everything stayed on the device. No account, no sync, no server, nothing to sign up for and nothing to leak. Photos came from Contacts if you pointed the app at a contact, and were read live rather than copied. English and Welsh shipped together from the first build, 64 strings in both, never one language leading and the other catching up.
It was deliberately small. Version one did the countdown, the list, adding and editing people, the contact photo, and a first-run walkthrough. Notifications, comparing dates between people, custom themes, sharing and sync were all named as out of scope and stayed out. It never went to the App Store.
Both recordings were driven by the app’s own UI test suite. The tests already knew how to launch the app into a known state, walk the first-run flow and tap through every screen, so producing a demo was a matter of pacing the steps and pointing a screen recorder at the simulator. Nobody touched the phone.
That is worth noticing, because it is the same pattern as everything else here. The parts a machine can do, a machine did well.
What was under the countdown
About 5,600 lines of Swift and 2,300 lines of tests, across the app and three local packages that held the model and storage, the visual components, and the background gradient. 93 issues filed, 66 pull requests merged, 68 commits, between 13 June and 18 July 2026. A universal build, with the iPad running a split view rather than a scaled-up phone layout.
Two decisions in there are worth keeping even though the app is not.
The first is that a button and a link were the same thing. Adding a birthday, editing one and opening the About screen did not push a screen directly. Each built the same internal intent an incoming link would decode to, and handed it to the same dispatcher, so the button and the URL ran identical code from that point on. The link grammar was small: a list, an add form, an about screen, a person, and a person’s edit form. Because those destinations had one path rather than two, tap behaviour and link behaviour could not drift apart, and the tests that fired every URL at the app were also testing the buttons.
The second is that the test suite drove the real thing. A launch argument swapped the store for a known set of people with fixed identifiers, so a test could assert what it was looking at. One test served the app’s own developer links page over a local connection and drove a tap through Safari into the app, which is the path a user actually takes when they follow a link. Those tests are why Fig 1 and Fig 2 exist.
Welsh was not a translation pass at the end. Every string landed in both languages in the pull request that introduced it, which is the only version of bilingual I have seen survive a schedule.
She looked at it and moved on
My daughter is the audience, and she was in the room. She did not like it. Not a bug report, not a missing feature, not a request for a different colour. She looked at it and moved on.
You can argue with a feature request. There is nothing here to argue with. There is also nothing to iterate on, because she did not stay long enough to give me a second data point, and that is itself the finding: the app never earned the four seconds it needed to explain itself.
An adult reads Fig 1 as a considerate first run. A child reads it as four screens before anything happens.
What the AI designer could not do
I designed this with an AI design agent, and some of what came back was genuinely good. The layout it landed on is one I still like looking at. It was quick, it was consistent, it held a visual language across screens I had not thought about yet, and it never got tired.
What it could not do was be a child, or have watched one. It works from a brief. A brief carries what I already know, so a brief from me could only ever encode an adult’s idea of what a child likes, expressed fluently. The agent made that idea look professional, which made it harder to see that the idea was wrong.
That is the specific failure mode worth naming. A weak design would have been obviously weak. A confident, well-executed design built on an untested assumption looks finished, and reads to its author as evidence that the assumption held.
Between us we made something an adult would call clean. Clean was not the requirement.
One child is not a sample, and I am not offering her reaction as evidence. The proof is the paragraph above it. A brief can only carry what its author already knows, so a design agent working from my brief could not supply the one thing I did not have. That holds whatever she had done.
So a designer is still needed. Not for the pixels, which the agent handled, and not for consistency, which it handled better than I would have. For the judgment about the person on the other side of the screen, which comes from having watched people like them, and which nothing in my toolchain has.
Where it stands
The board is closed and I am not planning to come back to it. The repository stays where it is rather than being archived, because the deep-link and test patterns in it are ones I have reused since, and the privacy page for the app stays live.
What I took from it is not about birthday apps. It is about where an AI collaborator sits in the work. The agent was fast, consistent and tireless, and every one of those qualities amplified whatever I handed it. What it could not do was tell me the brief was wrong, because the brief was the one input it had no way to check.
So the change is upstream of the tooling. The assumption that would be most expensive to get wrong now gets tested against a real person before an agent is briefed at all, because after that point everything that comes back looks like progress. Fluent output is not confirmation. It is the same assumption, rendered well.
That is the lesson, and it cost a finished app to learn it.