Case study · My own iOS app · Live on the App Store
Enkily takes a spoken thought and files it as a task, an event, a journal entry or a memory. Built solo and shipped to the App Store in thirteen days. The part worth writing about is what it refuses to do without permission.
No download counts, no user numbers, no revenue, and no version number. The App Store analytics credential returns a permissions error that is still unresolved, so I have genuinely never read a store-side figure for this app. There are numbers for the marketing website, and presenting those as App Store performance would be exactly the substitution I would flag in somebody else's reporting. This page is about how it was built and what it refuses to do.
First build uploaded on 2026-06-07. Submitted to App Review on 2026-06-11. Live on the App Store on 2026-06-20, with the next reliability release submitted the same day it went live.
That pace is only possible because the awkward decisions were made before the code, not after it. Two in particular shaped everything downstream.
The app opens an anonymous session the first time it launches. You can capture a thought before you have an account, because an app whose entire pitch is that capture costs nothing cannot open with a registration form. This is also why the internal activation metric counts people who opened the app rather than people who installed it, and why that distinction has to be stated every time the number appears.
A delete-all-data control that genuinely deletes, wired end to end rather than presented as a reassurance. If a toggle in a settings screen describes something the software does not actually do, everything else in that screen becomes a claim rather than a fact.
The product was repositioned around ADHD-first use partway through, which changed what good looked like. Frictionless lock-screen capture stopped being a nice feature and became the whole thesis.
The design decision the rest depends on
Letting a model respond to a private journal entry is not the same kind of feature as letting it sort a shopping list. Somebody writes something at their lowest moment and software answers. So the feature only runs when all five of these are true, and they are enforced in the code path rather than described in a policy document.
The user is deliberately in the journaling surface, not merely capturing.
An explicit over-eighteen confirmation, wired from zero call sites to enforced.
A setting that defaults to off. Nobody arrives with this switched on.
Separate, explicit consent to AI processing, under the App Store guideline that governs disclosure.
A safety classifier must return an explicit no-risk result, and the code waits for it rather than racing it.
The last one matters most and is the easiest to get wrong. A safety check that is started but not awaited passes every test and protects nobody, because the feature proceeds while the classifier is still thinking.
What the test suite could not see
Hundreds of tests passed. The feature was correct. On a real device it did nothing visible, and it was costing money every time.
The card displaying the AI response dismissed itself automatically after six seconds. The response arrived at about seven and a third. Every run made a real, billed request and rendered the answer into a view that had already gone.
No test could catch this. Tests wait deterministically for a stubbed response and never experience latency, so in the suite the answer always arrived instantly and the card was always still there. The bug lived entirely in the gap between how fast a stub is and how slow a network is.
The second bug was the mirror image: a feature that correctly did nothing, forever, because one of the five gates was refusing a consent the app had never actually asked for. Also invisible. Also only found by installing the thing and using it.
A suite proves the code does what was written. Whether a real user on a real device ever receives the result is a different question, and it is answered by installing the build and looking. Both bugs above cost money while producing nothing visible, and both were obvious within seconds of doing that.
A privacy policy describing what software will not do is worth very little next to a code path that cannot execute without an explicit, revocable, defaults-to-off permission. The second version survives a change of maintainer.
A classifier whose result arrives after the decision has been made is not a safety feature. It is an expensive log line. This is the single easiest place to build something that looks careful and is not.
The age gate could not be actuated by any automated harness. Confirming it worked took a person tapping a switch on a physical phone and watching both prompts appear. When a control genuinely cannot be tested automatically, that is a fact to schedule around, not to route past.
An audit works out which parts of your workflow are safe to automate, and what has to stay in front of a person. That order is cheaper than the reverse.
You speak or type a thought, and it routes to the right place on its own: a task, a calendar entry, a journal note, or long-term memory. The point is that capture should cost nothing. Deciding which bucket something belongs in is exactly the friction that stops people recording anything at all, so a model does that part and the person does not.
Because I have never read them. The App Store analytics key returns a permissions error and has not been resolved, so no store-side impression, page-view or conversion figure has ever been in my hands. There are numbers for the marketing website, and quoting those as if they described the App Store would be the kind of substitution I would flag in a client audit. When I can read the real ones, they can go here.
For the feature that lets AI respond to a personal journal entry: the user must be in journal mode, must have attested to being over eighteen, must have opted in through a setting that defaults to off, must have given explicit AI-processing consent under the App Store guideline that governs it, and the crisis classifier must have returned an explicit no-risk result that the code waits for rather than races. Any one of them missing means the feature does nothing at all.
For a to-do app, yes. For software that reads what someone wrote in a journal at two in the morning, the gates are the product. The interesting part is that they made the feature silently do nothing for a while, which is covered below, and I would still rather debug that than the alternative.
A passing test suite tells you the code does what you wrote. It cannot tell you whether a real person on a real device ever sees the result. Two bugs here were invisible to hundreds of green tests and obvious within seconds of installing the build, and both cost real money while producing nothing a user could see.
That is not the offer. This is here because it is evidence of how I ship AI into places where a wrong output is not a rounding error, and because a solo consumer app forces every decision about consent, safety and cost to be made explicitly rather than delegated to somebody else’s policy.