cmc/cleberg.net

My personal web garden & blog.

clone: git clone https://gitbay.org/cmc/cleberg.net.git

3239e8978f879af87a928866163173f66127e9f1

unsigned

author: Christian Cleberg <hello@cleberg.net> · 2026-08-11T21:12:19Z

Make the reply footer a snippet, not a rule

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/org-ssg.toml         | 14 ++++----------
 content/templates/post.html  | 10 ++++------
 content/templates/reply.html |  8 ++++++++
 3 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/content/org-ssg.toml b/content/org-ssg.toml
index 7cac59d..a1db6a0 100644
--- a/content/org-ssg.toml
+++ b/content/org-ssg.toml
@@ -41,20 +41,14 @@ dir = "templates"
 
 # Blog posts render through post.html — the shared layout plus a reply footer — the way
 # weblorg routes them through theme/templates/post.html. Everything else uses base.html.
+# Blog posts render through post.html, which adds the reply snippet. Nothing else does:
+# the live site also invites replies on garden notes and /now/, and that is a choice
+# rather than something a directory should decide. Any page opts in for itself with
+# `#+TEMPLATE: post.html`, and any post opts out with `#+TEMPLATE: base.html`.
 [[pages]]
 match = "blog"
 template = "post.html"
 
-# The live site invites replies on garden notes and /now/ too, but not on /uses/,
-# /tips/ or /salary/.
-[[pages]]
-match = "garden"
-template = "post.html"
-
-[[pages]]
-match = "now"
-template = "post.html"
-
 [highlight]
 theme = "InspiredGitHub"
 
diff --git a/content/templates/post.html b/content/templates/post.html
index e35ad64..ea5c28d 100644
--- a/content/templates/post.html
+++ b/content/templates/post.html
@@ -1,11 +1,9 @@
-{# A blog post, mirroring theme/templates/post.html. Everything but the reply footer is
-   the shared layout, so this extends it rather than restating it.
+{# A blog post: the shared layout plus the reply snippet.
 
-   Selected by the [[pages]] rule for blog/ in org-ssg.toml; a post that wants a different
-   layout says so with #+TEMPLATE:. #}
+   The snippet lives in reply.html so its wording is a file you edit rather than a line
+   buried in a layout — and so emptying that file removes it from every post at once. #}
 {% extends "base.html" %}
 {% block content %}
 {{ body | safe }}
-<div><a href="mailto:hello@cleberg.net">Reply via email &rarr;</a></div>
-<div><i>...or, comment on this post on <a href="https://bubbles.town/source/cleberg.net">Bubbles</a>!</i></div>
+{% include "reply.html" %}
 {% endblock %}
diff --git a/content/templates/reply.html b/content/templates/reply.html
new file mode 100644
index 0000000..333ffdb
--- /dev/null
+++ b/content/templates/reply.html
@@ -0,0 +1,8 @@
+{# The invitation to reply, kept apart from the layout so it can be edited, emptied or
+   dropped without touching how a post is built.
+
+   Included by post.html, which the [[pages]] rule routes blog posts through. A page that
+   wants it elsewhere says `#+TEMPLATE: post.html` for itself; a post that does not want
+   it says `#+TEMPLATE: base.html`. #}
+<div><a href="mailto:hello@cleberg.net">Reply via email &rarr;</a></div>
+<div><i>...or, comment on this post on <a href="https://bubbles.town/source/cleberg.net">Bubbles</a>!</i></div>