Commit c156621a77

c156621a773f144fb829a63be63b8af33506d975

parent: 17131d475e

Unsigned

cmc <hello@cleberg.net> ยท 2026-08-11 21:07 UTC

Settle the four remaining differences from the live site

- **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.

Layout: unified ยท split

content/org-ssg.toml +18 โˆ’1
@@ -45,6 +45,16 @@ dir = "templates"
45match = "blog" 45match = "blog"
46template = "post.html" 46template = "post.html"
47 47
48# The live site invites replies on garden notes and /now/ too, but not on /uses/,
49# /tips/ or /salary/.
50[[pages]]
51match = "garden"
52template = "post.html"
53
54[[pages]]
55match = "now"
56template = "post.html"
57
48[highlight] 58[highlight]
49theme = "InspiredGitHub" 59theme = "InspiredGitHub"
50 60
@@ -53,7 +63,10 @@ theme = "InspiredGitHub"
53# which is what the current site does too. 63# which is what the current site does too.
54heading_offset = 1 64heading_offset = 1
55toc = true 65toc = true
56section_numbers = false 66# On, because the live site has numbered headings โ€” inherited from Emacs' default rather
67# than chosen, but changing it is a design decision to make deliberately rather than a
68# side effect of switching generators. One line to flip when you want to.
69section_numbers = true
57 70
58# --- Generated pages ------------------------------------------------------------- 71# --- Generated pages -------------------------------------------------------------
59# These have no source .org file. weblorg produces the equivalents today through its 72# These have no source .org file. weblorg produces the equivalents today through its
@@ -116,3 +129,7 @@ template = "feed.xml"
116title = "cleberg.net" 129title = "cleberg.net"
117sort = "date" 130sort = "date"
118order = "desc" 131order = "desc"
132# Whole posts, not excerpts. The live feed carries full content, and a subscriber handed
133# excerpts instead would notice. Costs a render of every listed post whenever the feed is
134# rebuilt, which is the trade this is worth making for.
135include_content = true
content/templates/base.html +5 โˆ’3
@@ -8,12 +8,14 @@
8 Available here: page (.title .url .source .date .date_iso .tags .excerpt .toc 8 Available here: page (.title .url .source .date .date_iso .tags .excerpt .toc
9 .keywords), site, nav, root, stylesheet. See the org-ssg guide on Templates. #} 9 .keywords), site, nav, root, stylesheet. See the org-ssg guide on Templates. #}
10{#- The table of contents, in the shape Emacs exports it. `page.toc` is a tree of 10{#- The table of contents, in the shape Emacs exports it. `page.toc` is a tree of
11 {title, anchor, level, children}, and it is empty when the page has no headings or 11 {title, anchor, level, number, children}, and it is empty when the page has no
12 says `#+OPTIONS: toc:nil` โ€” so pages that opt out simply render nothing here. #} 12 headings or says `#+OPTIONS: toc:nil` โ€” so pages that opt out render nothing here.
13 The number is printed because [html] section_numbers is on; drop it if you turn
14 numbering off, or the contents will number what the headings do not. #}
13{%- macro toc_list(entries) -%} 15{%- macro toc_list(entries) -%}
14<ul> 16<ul>
15{%- for e in entries %} 17{%- for e in entries %}
16<li><a href="#{{ e.anchor }}">{{ e.title }}</a> 18<li><a href="#{{ e.anchor }}">{{ e.number }} {{ e.title }}</a>
17{%- if e.children %}{{ toc_list(e.children) }}{% endif %}</li> 19{%- if e.children %}{{ toc_list(e.children) }}{% endif %}</li>
18{%- endfor %} 20{%- endfor %}
19</ul> 21</ul>
content/templates/feed.xml +3 โˆ’4
@@ -3,9 +3,8 @@
3 from the site that served it, so every URL here is absolute โ€” which is what 3 from the site that served it, so every URL here is absolute โ€” which is what
4 `| absolute` needs [site] base_url for. 4 `| absolute` needs [site] base_url for.
5 5
6 One difference from weblorg: <description> carries each post's excerpt rather than its 6 <description> carries each post's full rendered HTML, as weblorg's feed does โ€” the
7 full HTML. org-ssg gives a collection template each entry's metadata, not its rendered 7 collection sets `include_content` to ask for it. #}
8 body. #}
9<rss version="2.0" 8<rss version="2.0"
10 xmlns:content="http://purl.org/rss/1.0/modules/content/" 9 xmlns:content="http://purl.org/rss/1.0/modules/content/"
11 xmlns:dc="http://purl.org/dc/elements/1.1/" 10 xmlns:dc="http://purl.org/dc/elements/1.1/"
@@ -29,7 +28,7 @@
29{%- for tag in post.tags %} 28{%- for tag in post.tags %}
30 <category>{{ tag }}</category> 29 <category>{{ tag }}</category>
31{%- endfor %} 30{%- endfor %}
32 <description>{{ post.excerpt }}</description> 31 <description><![CDATA[{{ post.content | safe }}]]></description>
33 </item> 32 </item>
34{%- endfor %} 33{%- endfor %}
35 </channel> 34 </channel>
content/templates/garden.html +1 โˆ’1
@@ -6,7 +6,7 @@
6<p>Notes in various states of growth. Some are stubs, some are developed. Browse 6<p>Notes in various states of growth. Some are stubs, some are developed. Browse
7around.</p> 7around.</p>
8<section> 8<section>
9<h2>&#127795; The Growth Stages</h2> 9<h2>&#129716; The Growth Stages</h2>
10<p>Instead of dates, these metadata labels show how mature a page is:</p> 10<p>Instead of dates, these metadata labels show how mature a page is:</p>
11<span><strong>&#127793; Seedlings:</strong> Rough notes, raw ideas, or "half-baked" 11<span><strong>&#127793; Seedlings:</strong> Rough notes, raw ideas, or "half-baked"
12thoughts.</span><br> 12thoughts.</span><br>
content/templates/tags.html +11 โˆ’4
@@ -1,12 +1,19 @@
1{# The tag index at /tags/, mirroring theme/templates/tags.html. Receives `groups` โ€” 1{# The tag index at /tags/. Receives `groups` โ€” every tag with its count โ€” rather than
2 every tag with its count โ€” rather than `pages`, because it lists tags and not posts. #} 2 `pages`, because it lists tags and not posts.
3
4 This deliberately differs in shape from the live weblorg page, which is one page with
5 every post inlined under an `#anchor` per tag. Here each tag is its own page, so a tag
6 has a URL worth linking to and the index stays short. The `id` on each entry keeps the
7 old `/tags/#audit` links landing in the right place โ€” they scroll to the tag and its
8 link, rather than 404ing or dumping the reader at the top of a long page. #}
3{% extends "base.html" %} 9{% extends "base.html" %}
4{% block main %} 10{% block main %}
5<h1>{{ page.title }}</h1> 11<h1>{{ page.title }}</h1>
6<p>Browse posts by topic.</p> 12<p>Browse posts by topic.</p>
7<ul> 13<ul class="tag-toc">
8{%- for tag in groups %} 14{%- for tag in groups %}
9<li><a href="{{ root }}{{ tag.url }}">{{ tag.name }}</a> ({{ tag.count }})</li> 15<li id="{{ tag.slug }}"><a href="{{ root }}{{ tag.url }}">{{ tag.name }}</a>
16<span class="tag-count">({{ tag.count }})</span></li>
10{%- endfor %} 17{%- endfor %}
11</ul> 18</ul>
12{% endblock %} 19{% endblock %}