Tagauthoring21

Everything else in 1.9

Five posts have covered what 1.9 is about: a post in two languages, the site in the language of the page, what stands in a deploy target before the first deploy, a host that only speaks FTP and one phone shortcut instead of two. This one is the rest, in the order an operator meets it. Most of it came from two people who set 1.9 up from nothing and upgraded a copy of a 6,600-post site, doing only what the docs said.

Read more

One shortcut instead of two

Sending a post from an iPhone took two shortcuts until 1.9: one to take the files from the share sheet, one to open the SSH connection. Written on a train walked through both. It is one shortcut now, imported rather than built, and it runs on a Mac as well.

Read more

Two languages, one site

Somebody writes in Czech, and some of the people who would read it don't read Czech. The usual answer is a second blog — a second archive, a second set of tags, a second feed — and within a year the two have drifted apart: a post fixed in one and not the other, a tag renamed on one side, a reader who switches languages and lands somewhere that no longer matches. blog.sh 1.9 gives a different answer: one site, and the other language beside it.

Read more

The last thing a recorder writes

Someone opens a post with a video in it and presses play. The connection is fine. The video is not large. Nothing happens for a while, and then the video starts all at once, as if it had been waiting for permission.

It had been waiting for the index.

Why it sits at the end

An MP4 is a handful of boxes laid end to end. One of them, mdat, is the picture and the sound. Another, moov, is the index: which frame is at which byte, how long the thing runs, what codec to hand it to. A player needs moov before it can show a single frame.

Read more

The address a post is about

Somebody sends you an article. You read it, and you have two hundred words to say about it -- not a review, the thing you noticed and one sentence about why. The post is mostly the other page, and the address it is about has to live somewhere.

Until this release the honest answer was: in a paragraph, like any other link. The card such a post opens with existed as a block -- the importers make them, out of Tumblr and out of Bluesky -- but nothing anybody could type produced one. The writer that turns a post back into markdown had no syntax for it, so edit on a link post offered to drop the card, and add <file> could not make one at all. This project's own release posts stopped being link posts after 1.3 for that reason. The tool had changed; the intent had not.

Three lines in the header

Read more

What a post is, not what it says

Five parts of a series written over a spring, and the third went out without its series: line. The site did what it was told. Part three sat at its date and nowhere else: off the series listing, out of the links from one part to the next, and out of the count the other four wear: part four's page called itself part 3 of 4, standing in the slot the missing post should have had. The fix was one word.

Getting to that word meant opening the article.

That is what edit does. It reads the post out of its file, writes the whole thing back out as markdown, opens it in an editor, and parses what comes back. For a post that is paragraphs and photographs the round trip is faithful and nothing is at stake. For a post carrying something markdown has no form for, it is not.

Seven rows

props <slug> gains [e] -- on a draft, on a scheduled post and on a published one alike.

Read more

The post that waited for a terminal

The post is written on the tram: a title, four paragraphs, two photographs with their descriptions. The switch above Send says Draft, which is what it says unless it is moved. Send, and the answer card comes back with the preview address. Then it sits. Putting a draft out was a command, and a command wants a terminal, and the tram has none.

1.6 asked for that decision at the wrong end: publish at the moment of sending, before the blog has rendered anything, or see the blog's own page and then find a keyboard. 1.7 closes that, and then closes the road the answer takes back.

One file, down the same connection

The answer card for a draft now carries a Publish button. Pressing it sends one file, called publish.txt, holding the slug and nothing else -- through the same share sheet, the same two shortcuts, the same SSH connection the post itself took.

Read more

Written on a train

A reader who was thinking about moving to this engine wrote to say he would stay where he was. He manages his blog from a phone, on the road, and a blog that can only be worked from a terminal was no use to him however fast it built. He was right.

1.6 answers him with two things, and with one thing it refuses to do.

A page on the blog itself

Set write: true and the build publishes a small editor at /write/: a title, the text, tags, photographs and video, each picture with its description. It wears the blog it writes to — its name, its palette, its language — and it offers the blog's own tags as you type, the ones used in the last twelve months first, so a tag is tapped rather than spelt a second way. A preview shows the post in the blog's own stylesheets. A row of marks above the text wraps what is selected and comes off again on a second tap. Above the send button, a Draft | Publish switch.

Read more

A post handed over as a file

Until 1.6 a post came from a person at a terminal. The wizard asked its questions, opened an editor, asked what to do at the end. Nothing else could write one: not a script, not a cron job, not a phone.

./blog.sh add post.md

does the same work with the markdown handed over instead of typed. No editor, no questions, no dialog at the end. A bare filename is looked for in incoming/, so the file can arrive by the same upload as the photographs, and it is deleted once the post is written.

Where the wizard would ask, this refuses

A person can be asked. A script cannot, so every question becomes a refusal that writes nothing: a photo that has not finished uploading, an empty body, a file that is not text, a second filename where one was expected. The alternative — guessing — was measured on the old code, where a byte-order mark in front of the header was taken for body text: three invisible bytes from a Windows editor and the post arrived with no title and no tags, named after the words "title:" and "tags:", exit 0. 1.6 reads the header through them.

--json: one object, nothing else

Read more

The link is the player

Embedding a video usually goes like this. Open the platform, click Share, click Embed, copy the blob of HTML it hands you, paste it into your post. What you have just filed in your own archive is somebody else's markup: an iframe, sometimes a script, a couple of tracking parameters and a class name from a design system you don't use. And when the platform changes its embed path — they do — every post you ever wrote that way breaks on the same afternoon.

Here you paste the address you would send a friend.

Two of them, actually playing

A video, with a caption:

Read more

Ten versions back

The engine has never had an undo. Editing a post rewrote its file, and what the post said an hour ago was gone — not because anything went wrong, but because a save is a save.

Now the previous text is kept before every overwrite, and [v] in a post's properties puts one back.

Before every overwrite, not just before an edit

A re-import is an overwrite too, and that turns out to be the case where this earns its keep. Editing a post by hand is deliberate; re-importing a source over a post you have since tidied up is the accident that eats an evening's work, and up to now the only recovery was a backup.

Ten per post, newest first.

Picked by recognising it, not by reading a timestamp

The list is one you walk like every other list in the wizard, and the row under the cursor shows what that version said — its title, or its opening words if it hasn't got one. Ten timestamps tell you nothing about which one is the version you want. Ten opening sentences tell you immediately.

Read more