Série./blog.sh v1.2

A blog engine that became an archive

The first post on this site is about a photo I put on Instagram in 2012. The link still works. The photo doesn't.

That post was about one archive — mine — and one rule: media comes home. This one is about what happened when that rule was applied to every platform I could find an export for.

The roster is closed

Twenty-two sources import now, in three groups.

Social networks: Bluesky, Facebook, Instagram, Mastodon, Pixelfed, Threads, Twitter/X.

Blogs and publishing platforms: beehiiv, Blogger, Ghost, Jekyll/Hugo and any markdown folder, LiveJournal, Medium, Movable Type and TypePad, podcasts (any feed with audio), Squarespace, Substack, Tumblr, Wix, WordPress and any RSS or Atom feed.

And dead sites: the Wayback Machine, for blogs whose platform no longer exists at all.

Číst dál

./blog.sh 1.2

./blog.sh 1.2 is out — the import release.

Eight import sources became twenty-two: every social network you are likely to have posted to, the blog platforms, and the Wayback Machine for blogs whose platform no longer exists.

Setting a site up is a conversation now. So is how it looks, with the candidate palette rendered on your own site before you keep it.

And a screen for walking an archive that got too big to scroll.

Setting up is a conversation now

Until this release, installing ./blog.sh meant copying two files and editing 277 lines of commented YAML before the first build would run. Everything was documented. That is not the same as being easy.

./setup.sh asks instead, and checks every answer as it arrives.

The questions that were quietly dangerous

Three settings could be typed wrong in a way nothing would ever tell you about.

The timezone. A typo here does not fail — Ruby falls back to UTC and says nothing — it just dates every post two hours off, forever. The wizard offers the zone from the machine's own database, unless the machine sits on UTC, which is a fact about a datacenter rather than about the person answering; then it suggests from the language you are being asked in. And it refuses anything that isn't a real zone.

Číst dál

Rescuing a blog that died in 2013

Every importer here reads an export file. That works right up until the platform is gone — and then there is no export to ask for, no admin to log into, and no account to recover. Posterous shut down in 2013. Blog.cz is gone. Your host is next, eventually.

For those blogs the twentieth import source is the Internet Archive.

Feed mode: what the crawler kept

The Archive did something useful without meaning to. For years it crawled blogs' RSS feeds — over and over, every few weeks, whenever a crawler happened past. Each capture is a snapshot of the last ten or twenty posts at that moment. Line them up oldest first and the overlaps reconstruct a history nobody saved.

That is what the importer does: reads the CDX index for the feed's address, deduplicates by digest so a hundred identical captures cost one fetch, pulls the original bytes through the id_ endpoint so the Archive's own toolbar never lands in your posts, and merges the overlapping windows the same way a re-import merges anything else.

Images come back through the same time machine.

Číst dál

A palette you can look at first

An earlier post here explains that every colour on this site comes from seven keys in a config file. That part hasn't changed. What has changed is that you no longer have to imagine what those seven values will look like before you commit to them.

Choosing between fourteen hex values is exactly as blind in a wizard as it is in YAML. So ./style.sh shows you.

Seven palettes, one keystroke

Whole palettes now ship in config/palettes.yml, light and dark both:

  • Default blue, warm, monochrome and high contrast — the four from the gallery on this site, whose light modes are exactly what that page showed. Their dark modes are new; the gallery only ever had light homepages.
  • Sunflower, cream and gold with olive links — the golden yellow stays on the tag pills, because yellow text on cream cannot be read and the accent here is above all a text colour.
  • Garden, greens and khaki.
  • Ocean, steel blue over navy.
Číst dál

Most of your Facebook isn't yours

The Facebook importer was built against a real "Download Your Information" export. The first useful thing it told me was a number I did not expect.

On that export, 95 % of the posts were not written on Facebook. They were mirrored in — from Twitter, from Posterous, from the whole crosspost era when every service politely offered to repost you everywhere else.

They are skipped, and counted

Those posts do not import. Not because they are worthless, but because the platforms they actually came from have their own exports, and those carry the originals: the full text, the real timestamps, the media at the size it was uploaded. A Facebook mirror of a tweet is a worse copy of something you can import properly from the Twitter archive sitting in the same folder.

Import both and your archive doubles, with the lesser version winning half the time. So they are recognized and skipped with a count in the summary, and FACEBOOK_CROSSPOSTS=1 overrides it if you disagree. Wordless check-ins and app stories are counted skips too.

Číst dál

Walking the archive

A post here recently argued that the wizard menu got shorter because operations on a post belong in the post, not in a menu. That still holds. This release adds a screen anyway, and the reason is worth stating: finding a post is a different job from doing something to one.

./blog.sh browse shows the same posts list does, as a screen you stay in.

What it is

Arrows and Page Up/Down through the whole archive. Filters by type, state and tag, with the count next to each. And a search that filters as you type.

The search is the site's own. Words are ANDed, "a quoted phrase" counts as one, -word excludes, and diacritics never decide a match. The query language and the folding live in lib/search_query.rb, next to a note that it and assets/js/search.js change together — because a query that means one thing in your browser and another in your terminal is worse than having no search in the terminal at all.

It searches the full text of every post, so under the selected row there is a line of that post's own text showing you why it matched.

Číst dál

Everything that's wrong, at once

Every abort in this engine is correct where it stands. Each one also reports exactly one problem — the first one, from wherever in the code it happened to be noticed. Fix it, run again, meet the next one. Repeat until the thing builds.

./blog.sh doctor reads what is on disk and tells you the lot in one pass, in whole sentences, each with a fix line written for somebody who does not know which file that setting lives in.

It goes after the silent failures

A loud error at least announces itself. The problems doctor concentrates on are the ones that never say anything:

Číst dál

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:

Číst dál