<feed xmlns='http://www.w3.org/2005/Atom'>
<title>cleberg.net.git, branch migrate-to-orgo</title>
<subtitle>My personal web garden &amp; blog.
</subtitle>
<id>http://git.krz.sh/cmc/cleberg.net.git/atom?h=migrate-to-orgo</id>
<link rel='self' href='http://git.krz.sh/cmc/cleberg.net.git/atom?h=migrate-to-orgo'/>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/'/>
<updated>2026-08-12T01:34:02+00:00</updated>
<entry>
<title>Finish the move off weblorg</title>
<updated>2026-08-12T01:34:02+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-12T01:34:02+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=ab149c1ae4fe38048fc2d32edac6061e7f3b4638'/>
<id>urn:sha1:ab149c1ae4fe38048fc2d32edac6061e7f3b4638</id>
<content type='text'>
Remove what the migration left behind, then cut build.py down to the work
orgo does not do: 443 lines to 168.

- Delete publish.el and theme/templates/, superseded by content/orgo.toml
  and content/templates/. theme/static/ stays; orgo publishes it as assets.
- Drop the tag builder, the org-source copy, and the helpers that only fed
  them. orgo generates /tags/ and a page per tag from a collection.
- Rewrite the README and the migration-era comments that explained the
  config by pointing at what weblorg used to do.
- Serve styles.css as authored. Minifying 1KB of CSS saved 52 bytes over
  the wire once compressed, which did not pay for a build step and a
  toolchain dependency.
- Stop wiping the output directory. The .orgo-cache.json inside it is what
  makes a build incremental, and orgo already prunes outputs whose source
  is gone and re-emits any that are missing. Production keeps .build/ and
  development gets .build-dev/, because production rewrites image URLs in
  the output and a shared directory would let one environment reuse pages
  rendered for the other.

An incremental build is byte-identical to a clean one, and the site output
is unchanged apart from the /uses/ stack row.
</content>
</entry>
<entry>
<title>Keep the build cache out of the deploy</title>
<updated>2026-08-12T00:26:42+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-12T00:26:42+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=5be4598b09a2685d73665b403bf80aad50b15834'/>
<id>urn:sha1:5be4598b09a2685d73665b403bf80aad50b15834</id>
<content type='text'>
.orgo-cache.json lives in the output directory because it describes that
directory, and the first orgo deploy put it on the server. Excluding it from
rsync stops that, and stops --delete removing it locally between builds.

The copy the first deploy left behind is gone from the server.
</content>
</entry>
<entry>
<title>Build with orgo</title>
<updated>2026-08-12T00:16:03+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-12T00:16:03+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=d10ca60103b924b6d182e09123af6ba4a5fffc77'/>
<id>urn:sha1:d10ca60103b924b6d182e09123af6ba4a5fffc77</id>
<content type='text'>
The generator changes; the steps around it that orgo does not do stay. Four of
them go, because it does:

- the blog index groups itself by year (a template, using page.year)
- the tags page is a collection
- the recent-posts list on the home page comes from the blog collection
- the sitemap is written once site.base_url is set

What remains is minifying CSS, copying the org sources for readers who want
them, and rewriting img.cleberg.net to /img/ so the onion serves images from its
own origin. That last one is why this script still exists.

Verified against the live site before deploying: 195 pages, 186 identical in
content, and every URL in the live sitemap still produced. The nine that differ
are the ones we chose — the reply footer is opt-in now, /tags/ has a page per
tag, and footnotes carry aria labels.

publish.el and theme/templates/ are left alone. They are weblorg's, and there is
no reason to delete a fallback on the same day the replacement goes live.
</content>
</entry>
<entry>
<title>org-ssg is called orgo now</title>
<updated>2026-08-11T21:48:53+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T21:48:53+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=7de79d1a3bf107550edb1defdda72a0008a35e1d'/>
<id>urn:sha1:7de79d1a3bf107550edb1defdda72a0008a35e1d</id>
<content type='text'>
The config file follows the tool: content/org-ssg.toml is content/orgo.toml, and
the build cache it writes is .orgo-cache.json. Nothing about the site changes —
196 pages, same output.
</content>
</entry>
<entry>
<title>Close the space before the full stop</title>
<updated>2026-08-11T21:22:19+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T21:22:19+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=093896152b80da4aac2396eaf32df6c94529f22e'/>
<id>urn:sha1:093896152b80da4aac2396eaf32df6c94529f22e</id>
<content type='text'>
The link's closing brackets were followed by a space, so the sentence ended
"through time ." on the page. Left over from removing something, most likely.

No others like it in the corpus.
</content>
</entry>
<entry>
<title>Drop the org-cite citation from the PHP comments post</title>
<updated>2026-08-11T21:18:39+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T21:18:39+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=32cc6cbaa410edec0ab9f8b540f473c1dfd02f40'/>
<id>urn:sha1:32cc6cbaa410edec0ab9f8b540f473c1dfd02f40</id>
<content type='text'>
`[cite/t:@brandur]` needs a citation processor and a bibliography, and there is
neither — so weblorg renders it as "?? (????)" on the live page today, and
org-ssg leaves the source text visible. The sentence already links Brandur's
post immediately after, so the citation was only supplying his name.

Now it just says his name. Correct under either generator, and one less piece of
machinery the site depends on for one word.
</content>
</entry>
<entry>
<title>Make the reply footer a snippet, not a rule</title>
<updated>2026-08-11T21:12:19+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T21:12:19+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=3c9514a6070d0fc0c4b2ffda2eef30981f266e54'/>
<id>urn:sha1:3c9514a6070d0fc0c4b2ffda2eef30981f266e54</id>
<content type='text'>
Routing garden notes and /now/ through post.html put the invitation to reply on
them because a directory said so, which is the wrong thing to be automatic — it
is a choice about each page, and I had made it site-wide to chase parity with
the live site.

Those two rules are gone; blog posts keep it. The wording now lives in
templates/reply.html rather than inside post.html, so it can be edited or
emptied without touching how a post is built, and editing it re-renders the 170
pages that include it and nothing else.

Any page opts in for itself with `#+TEMPLATE: post.html`; any post opts out with
`#+TEMPLATE: base.html`.
</content>
</entry>
<entry>
<title>Settle the four remaining differences from the live site</title>
<updated>2026-08-11T21:07:17+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T21:07:17+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=a26225589d9cda5328d70d7545e9919d3c0d3f8b'/>
<id>urn:sha1:a26225589d9cda5328d70d7545e9919d3c0d3f8b</id>
<content type='text'>
- **The feed carries whole posts again.** `include_content = true` on the feed
  collection, and the template embeds `post.content` rather than the excerpt.
  169 items, 2.9 MB, same as weblorg produces.

- **Section numbering on.** The live site numbers its headings — inherited from
  Emacs' default rather than chosen, but switching generators is the wrong
  moment to quietly redesign 174 pages. The contents list numbers to match. One
  config line to flip if you decide against it.

- **The reply footer follows the live site**: blog posts, garden notes and
  /now/, but not /uses/, /tips/ or /salary/. Two more `[[pages]]` rules.

- **Tags stay one page per tag**, deliberately unlike the live single page with
  every post inlined under an anchor. A tag with its own URL is worth linking
  to, and the index stays short. Each index entry carries the tag's slug as an
  `id`, so old `/tags/#audit` links still land on the right row.

Also fixes the garden emoji, which I had transcribed as 🌳 where the weblorg
template has 🪴 — taken from that template this time rather than typed.

Content now matches the live site on 192 of 195 pages. The three that differ:
footnote section markup, an `org-cite` citation neither generator renders
usefully, and the tags page above.
</content>
</entry>
<entry>
<title>Publish theme/static directly instead of copying it into content</title>
<updated>2026-08-11T20:31:39+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T20:31:39+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=4d3f7fe4d19b0bff06f53d11f34746b421c7c042'/>
<id>urn:sha1:4d3f7fe4d19b0bff06f53d11f34746b421c7c042</id>
<content type='text'>
org-ssg can read asset directories outside its source now, so the four files
copied in — gpg.txt, robots.txt, salary.csv and styles.css — go back to having
one home. `[build] assets = ["../theme/static"]` publishes that directory at /,
which is where weblorg serves it from too.

That also removes the note asking whoever comes next to keep two stylesheets
identical, and picks up styles.min.css as a side effect.
</content>
</entry>
<entry>
<title>Render the table of contents, and group /blog/ by year</title>
<updated>2026-08-11T19:28:56+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T19:28:56+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=584da4a4e0fec8873b3168ec5b0002a1bbc1c392'/>
<id>urn:sha1:584da4a4e0fec8873b3168ec5b0002a1bbc1c392</id>
<content type='text'>
Two of the differences the page-by-page diff against the live site turned up.

The TOC was the larger one: live has one on 171 pages and the org-ssg build had
none. `[html] toc = true` only *exposes* `page.toc` — rendering it is the
layout's job, and base.html never did. It now emits the same
`div#table-of-contents` Emacs does, from a recursive macro over the tree. The
anchors already matched, so every link lands where the live one does. Pages that
say `#+OPTIONS: toc:nil` get an empty tree and render nothing, which is why
/uses/, /now/ and /salary/ have no TOC here either — the same three as live.

/blog/ now breaks its list under year headings, as the live index does, using
`page.year` and minijinja's groupby. `group_by_year` at the top of blog.html
turns it off for one flat list.

After both, /blog/ matches the live page's content exactly, and 171 of 171 TOCs
are accounted for.
</content>
</entry>
</feed>
