How this site was built

Jarniel Cataluna ·

An agent made every part of this site — the code, the copy, the images, the design. Two of them fought back, and they were the two nothing could check.

Flat illustration on cream. A grid of small black page layouts in even rows, every one struck through with a pink diagonal stroke except a single one near the centre, which is circled in green.

Four went fine

Six things had to be made: the code, the copy, the images, the metadata, the visual design, and the tooling that drafts posts like this one. An agent made all six.

Four went fine.

Two fought back, and it took me a while to see what they had in common. The four that went fine are the four something can check. Does it compile. Does it deploy. Does the schema validate. Does the image come out at the right size.

The two that fought back were the copy and the look — where correctness isn't a category. Nothing tells you the copy is wrong. Nothing tells you the design is wrong. You either know, or worse, you don't.

Start with the look

Start with the look, because it fought hardest.

The first version was generic. Not broken — generic. It was a website. It was fine. It was the same website everybody gets.

I couldn't say what was wrong with it. I could see it instantly and describe it not at all. I know system design, admin panels, internal portals. I don't know design. So I'd say make it cleaner, or more modern, and get back a different generic website — because I was describing a feeling, and it was answering with an average.

The bottleneck was never the model. It was that prompting asks you to describe what you want, and I could only recognise it.

So I went looking at other people's work instead. Not to copy it — to find out what I responded to, which turned out to be something I could only learn by looking.

I found it eventually, and it had a name: neo-brutalism. Hard edges, flat colour, visible structure, nothing apologising for itself.

Found, not chose. It felt less like a decision than like recognising something that had already been true.

A genre label buys you the genre

Typing that word into a prompt changed things immediately, and not enough.

A genre label buys you the genre. I asked for neo-brutalism and I got neo-brutalism — the black borders, the hard offset shadow, the acid yellow, the one loud typeface. All correct. All still an average, just of a smaller set.

I know how far short it fell, because the rounds kept going after I found the word. The last round of candidates is entirely brutalist and still being narrowed against itself. If the word had been the answer, that round wouldn't exist.

Giving up on describing

What worked was giving up on describing.

Instead of asking for a style in words, I had it generate candidate designs as images — flat sketches of a page, no browser chrome, no device frame, palette fixed and stated. Then I looked at them and threw almost all of them out, and generated more from whatever survived. That is what the rounds were.

It worked because it asked me the only question I could answer. Not what do you want, which I could not say at any point. Is it this one, which I knew instantly, every time, without having to explain myself.

The document that accumulated

Somewhere in all that rejecting, a document started accumulating.

Every time I corrected something or adjusted a prompt, the correction went into it — not the sketch, the reason. Border weight. What the accent colour is for. Which typeface does which job, and why the other one doesn't.

It was never written as a brief. It was written as a receipt, and it is by a long way the largest document in the repository.

The point of that document isn't that it's thorough. It's that it survives the session.

A preference held in a conversation lasts as long as the conversation. Explain a border weight, get the border weight, come back tomorrow to a fresh context and explain it again — and the second explanation won't match the first, because you are reconstructing a decision instead of reading one.

Written down, it stops being something I have to remember and starts being something an agent arrives already bound by. Every session inherits every no I ever made, without me being in the room.

The documents are the orchestration

Which is what I mean by orchestration, and it is less exciting than the word suggests.

There is no swarm here. No agents negotiating with each other, no clever topology. What there is: a design system, a product brief, a glossary of words this project doesn't use, decision records holding the reasoning behind the awkward choices, a policy on pull requests, and a set of skills describing how particular jobs get done.

More words telling an agent how to build the site than the site has published.

The documents are the orchestration. Everything else is typing.

There is a limit to this, and it took me longer to see than it should have.

A document can only record a decision that has already been made. It is very good at holding one still. It is no help at all in reaching one.

Which explains why four of the six were easy. Those decisions were made years ago, by other people, and I already knew them. The look was hard because nobody had decided it yet, and it was mine to decide.

The copy that read well and said nothing

The copy was the second undecided thing, and it failed in a way I nearly missed entirely.

It read well. I remember reading it and thinking it read well. Then I read it again and there was nothing in it — every sentence grammatical, confident, and transferable to anybody's site.

Bad is easy; you delete bad. This was good on the first read and empty on the second, and nothing about a first read tells you which one you are holding.

Some of that was my own doing.

Nothing on this site names a client, a product, or an employer other than my own. The work is real and most of it sits under agreement, so every sentence about it has to describe the shape of a thing without identifying it.

The rule is correct and it made the writing worse before it made it better. Take the names away and the fallback is abstraction — enterprise platforms across multiple sectors — because the specific thing it wanted to say was the forbidden thing.

What fixed it wasn't writing less specifically. It was finding something else to be specific about.

Over a decade of software engineering across four titles at one company. No client named, nothing disclosed — and still checkable, still faintly unusual, still unmistakably mine.

The generic version wasn't vague for want of information. It was vague because it reached for the one thing it couldn't have and then gave up.

The failure my review cannot reach

There was a worse failure underneath the generic one, and I nearly reported only the first.

It assumed things. Given a partial history it wrote the connective tissue — the responsibilities a title implies, the outcomes a role like that usually produces, the shape a career like mine normally takes.

Fluent, reasonable, and not mine.

Which is a different problem from the first one, and a much quieter one.

Vagueness announces itself. You can feel it on the second read, and anyone can feel it, about anyone.

Invention doesn't. A fabricated sentence reads as a fact — it has the texture of the true sentences around it, because it was built out of them. It passes the second read. It passes every read.

I caught them because it was my decade. I didn't verify anything — I knew the sentence was wrong the way you know a stranger has got your name wrong.

Which means I would have missed every one of them if they had been written about somebody else. I am certain of that, and it is the part of this I find hardest to put down.

This is the failure my own review cannot reach, and I would have told you otherwise a month ago.

Every change here gets read twice, by two passes kept deliberately apart — one against the project's written standards, one against whatever asked for the work. A sentence inventing something about my career contradicts neither. It is perfectly consistent with every document in the repository, because the thing it contradicts is not in the repository.

The documents can hold a decision still. They cannot hold a fact they have never been told.

One correction, because I made every decision is a claim you should discount on sight.

The metadata on this site goes well past what a portfolio needs — structured data, plain-text mirrors of every post, machine-readable indexes. I didn't ask for any of it. It was proposed, I recognised it as right, and I said yes.

Which turns out to be a different kind of gap from the design one. Not knowing what I wanted the site to look like was a gap nobody could close for me; there was no correct answer sitting outside my head waiting to be fetched. Not knowing how a page gets read by a machine was a gap anybody could close, in a sentence, because the answer existed and someone already had it.

I had been treating both as things I'm not good at. They are not the same disability. One is closable by being told. The other is only closable by choosing, and choosing is not a thing that can be done on your behalf.

While I was writing this, I asked for the design to be reviewed. The first thing it came back with was that the blog index was broken — the cards fading out on load and never appearing unless you scrolled.

It was measured rather than guessed. Reproduced over and over, the page read each time, the exact line named. I believed it, because everything about it had the shape of a real finding.

It was wrong. Every one of those measurements had been taken through a browser tab that was never rendering, and a browser that is not rendering cannot run the thing that does the revealing. Nothing was broken. The page had been working the whole time, for everybody who was not a program looking at it.

So: the same failure as the copy, arriving from the other side. Not a sentence invented about my career but a defect invented about my site — fluent, evidenced, consistent with every document in the repository, and false.

I have spent this entire post describing that failure. It still took somebody opening the page and looking to catch it.

← All posts