Star it to publish it
The comments under these posts are replies to a toot. That has been the whole system since the beginning, and its one weak spot was always that it is all or nothing: every reply appears, or comments are off.
comments.approval: fav is the third answer. A reply appears under the article once I favourite it, from whatever client I happen to have open.
No queue, no dashboard
That is the point of doing it this way. A moderation queue is a second interface, with a second login, that you visit specially — which means you visit it late, or not at all. Here the interface is the app the comments already live in. I read the reply where I was going to read it anyway, and approving is one tap in that same place.
Two rules keep the result readable rather than merely filtered. My own replies need no star, because nobody stars themselves and half of every exchange would otherwise vanish. And a reply is shown only if everything between it and the announcement is shown too — an approved answer to a rejected comment answers nothing.
What it costs, and the costs are real
A favourite is public. On both networks. Approving is also endorsing in the eyes of anyone who looks, and every star handed out over the years is retroactively an approval. A private signal — bookmarks — would not carry that, and is the obvious second mode if this one chafes.
The moment you switch it on, every comment on the site disappears. Moderation publishes what has been starred, and at that moment that is nothing. A site with years of replies goes quiet in one rebuild. Plan the switch for an hour when you can go and star the keepers, and run ./scripts/refresh-sidebar.sh --full afterwards to settle the old posts on the spot instead of within the week.
Approval is not instant. Up to one cron interval — and up to a week under a post older than about three months, since old posts are only refreshed occasionally. "Did I favourite this?" is a question only an authenticated request can ask, and the token cannot be shipped to a browser, so cron reads the thread and writes the answer; the page renders from that. ./scripts/refresh-sidebar.sh --full does it now instead of eventually.
It makes an older promise on this site conditional. There is a post here saying there is no comment database — nothing to migrate, back up, or moderate at 2am. With approval on, only the last third of that stays true. What has been starred is written to a file the pages read, rewritten from the source on every cron run, with no interface anywhere that can edit it: a cache rather than a database, but other people's words on my disk all the same.
And somebody's deletion can outlive itself here. A reply deleted at the source leaves this site at the refresh cron's cadence rather than immediately — under an old post, up to a week later. --full settles it on the spot, but the lag is part of the price rather than a setting, and it is the part that is paid by someone other than me.
It keeps replies off the blog, not off the network. The thread stays public and this site still links to it. Block, mute and report remain the tools for the rest.
The side effect nobody asks for
With the thread already read on the server, the visitor's browser stops contacting the network at all — and the page's content security policy drops its grant to the instance along with it. The live thread was the one client-side exception to no third-party requests from the visitor's browser. A moderated thread is not live, so the exception lapses with it.
Avatars still come from the instance hosting them. Everything else arrives from this domain.
Turning it on
comments:
approval: fav # or "off" (the default)
Three things have to be true, and ./blog.sh doctor --online says so when they are not: the sidebar cron has to be running, a Mastodon token needs read:statuses alongside write:statuses — a token without it gets a perfectly good answer with the favourited field left out, which reads as "approved nothing" — and you have to go and star the ones worth keeping. On Bluesky the app password you already have is enough.
