Skip to content

./blog.sh 1.2

Choose a tag to compare

@DanielSnor DanielSnor released this 11 Aug 04:38
· 35 commits to main since this release

./blog.sh 1.2 — the import release.

Eight import sources became twenty-two, and everything else here grew around the same idea: a blog you wrote somewhere else should be able to come home whole, and stay readable after the platform that held it is gone. Two wizards arrived with it, a queue, a screen for walking the archive, and a way to find out what is wrong with an install. Nothing to migrate: git pull, rebuild, deploy — with one caveat at the bottom for archives imported under 1.1.

Bringing a blog in

  • Fourteen more sources. Ghost, Substack, Medium, Blogger, Squarespace, Wix, beehiiv, Movable Type/TypePad and LiveJournal joined the blog platforms; Facebook and Threads closed the social roster; podcast feeds and markdown trees (Jekyll, Hugo, any folder of .md with front matter) import too. Ghost's export carries no images at all, only references back to the running site — import before the old site goes dark; a markdown tree needs no network whatsoever.
  • The Wayback Machine is a source. For a blog whose platform no longer exists, the engine rebuilds the site from the Archive's captures of its feed — or from archived post pages where there never was a feed, which is how a blog.cz or b2evolution site comes back. WAYBACK_FROM/WAYBACK_TO narrow a run to a date window.
  • Media comes home, from every source. Images, audio and video download next to the post and the post references the local copy, so an import outlives the CDN it came from. A migrated blog can keep its old addresses too: posts carry the paths they answered at before, and the build serves a redirect at each.
  • The source menu is two levels (blog platform, social network, dead site); a piped run still gets one flat numbered list, and the migrate_*.rb scripts are unchanged.

Setting a site up, and making it look like yours

  • ./setup.sh — setting a site up is now a conversation. Instead of copying two files and editing 277 lines of commented YAML, it asks, and checks each answer as it arrives: the timezone against the machine's own zone database, the address written to both config/site.yml and env.sh, the Mastodon token verified against the instance — which also hands back the numeric account id the sidebar widget needs and is most often filled in wrong.
  • ./style.sh — the appearance half. Palette, banner, about, footer, social icons, sidebar widgets, fonts, analytics. Seven palettes ship with the engine, and a candidate can be looked at before it is kept: your own site rendered in the new colours, and on a deployed site answered with a QR code — so a palette picked at an SSH prompt can be judged on a phone.
  • Neither writes anything until the end: answers are collected, the diff is shown with secrets masked, one confirmation covers the lot. Your config keeps every comment it had, and editing it by hand still works exactly as before.

Living with an archive

  • ./blog.sh doctor reports everything wrong with a configuration at once, each with the line that fixes it, and concentrates on what fails silently — an unknown timezone, a widget that can never show anything, a scheduled queue that nothing is publishing. It runs on configs too broken for anything else to load.
  • ./blog.sh queue is a screen for scheduled posts: reorder, publish now, retime, return to drafts. Moving exchanges times with the neighbour, so the set of occupied slots never changes.
  • ./blog.sh browse walks the archive instead of scrolling past it — arrow keys, filters by type, state and tag, and a search that narrows as you type in the site's own query language. Space previews, Enter edits and comes back to the same row.
  • Builds and deploys take a lock, so the two crons and a person at the CLI can no longer rewrite the output directory at the same time.

Fixes

Every import source was put through a real export from the platform it claims to read, and most were losing something quietly — whole posts, pictures, links, or the difference between a draft and a published post. A password-protected WordPress post was published in full; every published Medium article was skipped for want of an id; a Blogger body arrived as a block per fragment, one post split into 105 of them with 29 links down to 8. Alongside those, a long list of corrections to editing, publishing, scheduling, the terminal screens and the crons, including a trash that could throw away another post's only backup and a scheduling path that was dead on every route into it.

The full list, grouped by area rather than by the round that found it, is in the changelog.

Upgrading

git pull, rebuild, deploy. Nothing to migrate, and every new configuration section is optional. Expect the first deploy to be a long one: every page carries a theme-color now, so all of them are rewritten once and the whole site uploads.

The one caveat is media numbering, and only for archives imported under 1.1: a failed download used to hand its number to the next image, so a post that reported failed media back then may shift a filename on re-import. Delete those posts' media directories first — the 1.1 run's summary named them — or import into a fresh tree.

Menu positions moved with the new screens, so a scripted printf "N\n" | ./blog.sh may land somewhere else than it did; the CLI commands are the stable interface. Rolling back to 1.1 builds, but do not write under it: 1.1 renders what it never knew about as best it can, and re-saving a 1.2-written post can lose text.

Seen in the wild: blogsh.app — the project site, which runs on this engine — and sean.cz, the archive it was built around, now 4400 posts reaching back to 2003.

MIT licensed. README · install · operations · importing · localization