I wrote two documents.
One is 6,188 lines. The other is half a page of text, rearranged five times in half an hour.
Code written: still none.
The first document is read by a machine. The second by a stranger. Those, it turns out, are two different professions.
🧾 Six thousand lines for an app with one user
Thirteen files, one commit.
Business requirements. Technical requirements. A breakdown of what the prototype already does. A milestone plan. Six task files, from milestone zero to milestone five. And a file of project rules.
Not one line of Swift. Not one open Xcode window.
If you're putting up a building, you think about the foundation first.
Then there's a plan.
And only then does anybody pick up a tool.
Development works the same way, if you want it done properly. But first things first.
I already had two answers and was missing the third.
Two months of prototype answered: does this work for me. Yes. Every day.
The page answered: does the idea read. Seems so.
Neither of them answers what it is that I'm actually building.
And that one gets written as a list, not as prose. Prose can sound convincing while being nothing at all. A list can't: on a list you see immediately where a decision wasn't made, only walked around.
🤖 The specification that isn't for a human
Now the part that isn't obvious.
Open any of the task files and it isn't a description, it's a work queue. Everything in the imperative: build, add, implement. And beside it two lists — patterns allowed, patterns forbidden.
Apple's native frameworks only.
No third-party dependencies.
None of that is written so somebody can understand how the app works. It's written to be worked from. And in the same commit there's a file of rules for the assistant.
Which leads to a conclusion that runs backwards to the usual one.
One person with an assistant needs more documentation than one person without. Not less.
Specifications used to exist so that people could agree with each other. One person has nobody to agree with — which is why side projects don't have them, and quite right too. But a specification stopped being a document and became input. And input pays for itself even in a team of one.
Last time I said the page had got cheap, and that this is why the order of the work changed. Here is the same thing from the other side: execution got cheap, and that is why the volume changed.
🗣 How this actually got written
I didn't type 6,188 lines.
I talked. In a stream, out of order, in broad strokes — I needed to get it all out before there was anything to make requirements from. No structure, no attempt to phrase it nicely.
Then the feedback came back. Questions that led somewhere. And step by step it assembled itself: first what for, and only after that how.
The rule in a conversation like that runs backwards to the usual one as well: say more, not less.
Say less and the gaps get filled in for you.
Say more and whatever didn't land comes back as a question.
Whatever goes unsaid turns up later, inside the finished document.
And what comes out at the end has to make sense to two people: the one who thought it up, and the one who has to work from it tomorrow. Both of them are me.
🧊 What's frozen
At the end of the rules file there's a list of decisions that can't be reopened without a separate conversation. There are ten of them. These are the four I'm holding hardest.
A snippet has no title. A snippet is text. That's all. A title would mean that every time I save a line I have to invent a name for it, and I'm saving that line precisely because I don't want to invent anything.
Privacy belongs to the board, not to the snippet. The difference looks technical, but it's about how many times a person has to decide. Protection on the snippet and you decide every time. Protection on the board and you decided once, and after that you just put the thing where it belongs. The same idea as the canvas: space instead of properties.
Collision detection is out. The canvas is unbounded and blocks are allowed to overlap. I spent a piece of my life on those algorithms in the prototype and got nothing out of them but twitching rectangles. Sometimes the right optimisation is a deletion.
Mac first. iPad and iPhone in version two. The page says "coming soon to Mac, iPhone & iPad", and that's true: the page says where we're going. The specification picks the order.
And in the same list, on a line of its own: 24 snippets free.
Written down. Frozen.
🔀 The second specification
Then I opened my own page and didn't understand it in ten seconds.
The exact test I had invented myself.
That's the one thing a landing page does honestly: it waits until you've forgotten that you wrote it.
What followed was five passes back to back, 8:13 to 8:42. The morning train.
Refreshed the page.
Added analytics.
Changed the styling.
Reordered the sections.
Reordered the sections again.
From the outside, flailing. In fact this is what work looks like when an edit costs a minute: when a change is expensive you think and you choose, when it's free you try it and look.
(The analytics, by the way, went onto a page that exactly zero people know about. Adding them and not looking is available any time. Not adding them and later wanting to look is not.)
And the sections, it turns out, had been moving the same way every time. I only noticed on the fifth pass: every rearrangement pushed the features further down and pulled the reason further up.
Today's last commit is called, literally: section order (why I build this).
And that's where it landed.
The order of the blocks isn't styling. The order of the blocks is the argument.
A page that opens with features says: here's what it can do.
A page that opens with a person says: here's why you can believe it.
I have no reviews. No downloads. No company behind me. Not one number worth showing.
What I have is a person explaining why he's building this.
Nothing else, so far — and that turned out to be the only thing worth putting first.
🔌 Engineer honesty moment
I'll start with the freshest one. It's ten minutes old.
I called this diary "parts" to begin with. Part one, part two — like a collection of articles. It isn't a collection. It's a diary, and the entries in a diary are days. Renamed.
But the address of an entry is generated once, at publication, and part-1 is in there forever.
A draft title leaked into a URL. It happens.
Now the real one.
This project's .gitignore has one line in it.
.idea/
A JetBrains folder. It has nothing whatsoever to do with a native Mac app. It's in there because my fingers remember ten years of front-end, and the first thing I do in a new repository is ignore an IDE this project doesn't have.
Nobody put .DS_Store on the list.
So in that same commit, right next to six thousand lines of engineering rigour, sits a housekeeping file that macOS drops into a folder just because you looked at it. Six kilobytes. It's still there.
I wrote a document about which patterns are forbidden, and committed litter from Finder.
One more, while I'm here: I spent all of that rearranging blocks and never touched a single word inside them. And the words in them, I remind you, were written by a machine.
Half an hour ordering the arguments in a text that doesn't exist yet.
And it was the right call. Order works before words do.
💬 A question
How much do you write down before you start?
I honestly thought the answer was "nothing" — and that this was the mark of an experienced person, one who keeps it all in their head.
Turns out I had simply never worked alongside anything that can read.
Tell me how it goes for you 👇
Next, I suppose, it's time to actually open Xcode.
The one that has never been opened, with not one line of Swift behind me. Territory next to mine, and not mine.
Then again, when has that ever stopped me 😉