<feed xmlns='http://www.w3.org/2005/Atom'>
<title>cleberg.net.git/content/org-ssg.toml, branch main</title>
<subtitle>My personal web garden &amp; blog.
</subtitle>
<id>http://git.krz.sh/cmc/cleberg.net.git/atom?h=main</id>
<link rel='self' href='http://git.krz.sh/cmc/cleberg.net.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/'/>
<updated>2026-08-12T01:35:15+00:00</updated>
<entry>
<title>org-ssg is called orgo now</title>
<updated>2026-08-12T01:35:15+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=5d60a70d6a963c234d311ca87829cf3150f72ef6'/>
<id>urn:sha1:5d60a70d6a963c234d311ca87829cf3150f72ef6</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>Make the reply footer a snippet, not a rule</title>
<updated>2026-08-12T01:35:15+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=3239e8978f879af87a928866163173f66127e9f1'/>
<id>urn:sha1:3239e8978f879af87a928866163173f66127e9f1</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-12T01:35:15+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=c156621a773f144fb829a63be63b8af33506d975'/>
<id>urn:sha1:c156621a773f144fb829a63be63b8af33506d975</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-12T01:35:15+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=17131d475ea658e3feeb37f8f01900f1285fe128'/>
<id>urn:sha1:17131d475ea658e3feeb37f8f01900f1285fe128</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>Route blog posts through post.html</title>
<updated>2026-08-12T01:35:15+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T18:51:10+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=42bf4bae9d582abd56758c1fcc7741419161fe7e'/>
<id>urn:sha1:42bf4bae9d582abd56758c1fcc7741419161fe7e</id>
<content type='text'>
The reply-by-email and Bubbles lines were emitted from base.html behind a test
on the page's URL, because org-ssg had no way for a page to pick a layout. It
does now, so they live in a post.html that extends the shared one — the same
split weblorg has between theme/templates/base.html and post.html — selected by
a [[pages]] rule for blog/.

All 169 posts carry the footer; /blog/ itself does not, being a generated
listing rather than a post.
</content>
</entry>
<entry>
<title>Bring the org-ssg templates to parity with the live site</title>
<updated>2026-08-12T01:35:15+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T18:41:18+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=9049e20a29fb54245079ec19ae4a503e3f8e2799'/>
<id>urn:sha1:9049e20a29fb54245079ec19ae4a503e3f8e2799</id>
<content type='text'>
The org-ssg build rendered the right content in the wrong chrome. Closing every
difference found by comparing it against theme/templates/ and the live pages:

- base.html: Home link written by the layout rather than the site title, a
  &lt;title&gt; of "Page - cleberg.net" (bare "cleberg.net" on the home page, via a
  subtitle block), author/description/og meta, the RSS alternate link, four
  rel="me" identity links, favicon, skip link, &lt;main id="main-content"&gt;,
  aria-label on the nav, and the real footer.
- home.html: the h1 is "Christian Cleberg" (the collection's title), and the
  email line has its GPG link back.
- blog.html and garden.html: the two listings carry their own prose on the live
  site — the search/RSS hint, and the garden's growth stages — so they are no
  longer sharing the generic list.html. Tag pages still use it.
- tags.html: "Browse posts by topic."
- Blog posts get the reply-by-email and Bubbles lines. org-ssg has no per-page
  template selection, so the layout keys off the page's URL prefix.
- Tags leaves the nav, which the live site does not have.

feed.xml is new: the footer links /feed.xml and nothing was generating it. It
is a collection whose template happens to be XML. Its &lt;description&gt; carries
each post's excerpt rather than the full rendered body, which weblorg's feed
does include — a collection template gets each entry's metadata, not its HTML.

base_url is now set, since canonical links and a feed cannot be relative. Page
links stay relative, so a preview build still works from any directory.

gpg.txt, robots.txt and salary.csv are copied in from theme/static/: weblorg
publishes that directory to the site root, and org-ssg publishes from content/,
so /gpg.txt was a 404. styles.min.css is deliberately not copied — it is
gitignored build output, and the tracked styles.css holds the same rules.
</content>
</entry>
<entry>
<title>Order the org-ssg nav to match the live site</title>
<updated>2026-08-12T01:35:15+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T07:27:28+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=517926849ed9477def1de54c7b9b5e53eed46fe5'/>
<id>urn:sha1:517926849ed9477def1de54c7b9b5e53eed46fe5</id>
<content type='text'>
Salary rendered before Blog and Garden because the two section indexes are
generated by collections, and an explicit nav could only name source files —
generated pages were appended after everything listed. org-ssg now accepts a
generated page's output path in `nav.pages`, so listing all three puts them in
the order the live site uses. /tags/ stays unlisted and lands last.
</content>
</entry>
<entry>
<title>Add an org-ssg build alongside the weblorg one</title>
<updated>2026-08-12T01:35:15+00:00</updated>
<author>
<name>Christian Cleberg</name>
<email>hello@cleberg.net</email>
</author>
<published>2026-08-11T07:20:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.krz.sh/cmc/cleberg.net.git/commit/?id=f1b8d6d4a89c5d33615556af65aadeb71e7800cb'/>
<id>urn:sha1:f1b8d6d4a89c5d33615556af65aadeb71e7800cb</id>
<content type='text'>
Builds the same site with org-ssg instead of weblorg, reproducing all 182 URLs the
current .build output has, plus 13 per-tag pages it does not.

    org-ssg serve content -o /tmp/preview      # write, with live reload
    org-ssg build content -o _site --strict    # build, failing on broken links

content/ is the source because it is the URL root: content/blog/post.org publishes at
/blog/post.html. Pointing at the repository root instead would prefix every URL with
/content/ and copy build.py, publish.el and LICENSE into the site as assets.

Added:

- content/org-ssg.toml — site metadata, an explicit nav, and four generated pages:
  the home page, the blog index, the garden index, and tag pages with an index. URLs
  come from #+SLUG:, which is why 2018-11-28-aes-encryption.org still publishes at
  /blog/aes-encryption.html.
- content/templates/ — base, home, list and tags. Plain layouts using the .post-list
  classes styles.css already defines, not a port of theme/templates/, which are
  templatel and a different language.
- content/styles.css — a verbatim copy of theme/static/styles.css, because org-ssg
  publishes assets from inside its source directory. `diff` between the two should stay
  empty; consolidate them if this migration goes further.

Removed content/index.org. It held only #+title and #+description, both now [site]
settings, and a generated home page cannot share a URL with an authored one — org-ssg
fails that build rather than picking a winner. Restore with
`git checkout content/index.org`, but then the home collection needs a different output.

Nothing in the weblorg setup changed. publish.el, theme/ and build.py still work as
before, so both builds coexist until one is chosen.

Known difference: the nav renders Home, Salary, Blog, Garden, Tags — explicit source
pages come before generated ones, where the live site orders Salary last.
</content>
</entry>
</feed>
