Comments network (optional): Mastodon or Bluesky

Getting started — part 9 of 10

Every published post is announced on the configured network, and replies to that announcement are the post's comments. A reply's pictures appear under its words -- thumbnails linking out to the full image, loaded from the commenter's own network the same way their avatar already is; a reply marked sensitive keeps its pictures to itself. Configure exactly one of the two -- the build refuses a config with both, since a discussion split across two networks serves nobody. Without either section, everything else still works; publishing just skips the announcement (logged, not an error).

Mastodon:

  1. In config/site.yml, uncomment the mastodon: block -- the header line included, which is the half that is easy to miss -- and set mastodon.instance. This switches on comments, per-post stats and the auto-toot on publish.
  2. On that instance: Preferences → Development → New application, scope write:statuses. Put the token into env.sh as MASTODON_ACCESS_TOKEN.
  3. For the "recent toots" sidebar widget, widgets.toots.account_id wants the numeric account id, not the @handle -- find it at https://<instance>/api/v1/accounts/lookup?acct=<username>. (The widget's instance falls back to mastodon.instance.)
  4. mastodon.toot_length is your instance's character limit, 500 by default. Set it if yours differs -- the announcement's perex is budgeted against this number, so a limit set too high gets the post rejected at publish time and one set too low just wastes room. mastodon.link_length is the other half of that arithmetic: Mastodon charges every link a flat 23 characters whatever it measures, and says so in its own API (characters_reserved_per_url). Leave it alone unless your server answers with a different number.

Bluesky:

  1. In config/site.yml, set bluesky.handle (e.g. you.bsky.social); bluesky.pds only if you self-host a PDS.
  2. On Bluesky: Settings → Privacy and security → App Passwords (bsky.app/settings/app-passwords) → create one, and put it into env.sh as BLUESKY_APP_PASSWORD -- never the account password.
  3. Announcements fit Bluesky's 300-grapheme limit automatically (the excerpt shrinks; title, link and hashtags never do), with the link and hashtags clickable. Comments are read from Bluesky's public AppView by the visitor's browser -- no token involved on the page.

Optional: publish only the replies you star.

By default every reply to the announcement appears under the article. comments.approval: fav in config/site.yml changes that to: a reply appears once you favourite it, from whatever Mastodon or Bluesky client you already use. Your own replies need no star. Everything else stays on the network and off the blog.

comments:
  approval: fav      # or "off" (the default)

The moment you switch this on, every comment already on the site disappears. Moderation publishes only what you have starred, and at that moment that is nothing -- a site with years of replies goes quiet in one rebuild. They come back one star at a time, so plan the switch for a moment when you can go and star the keepers right away, and run ./scripts/refresh-sidebar.sh --full once afterwards to settle old posts on the spot instead of within the week.

Three things have to be true for it to work, and ./blog.sh doctor (add --online for the token check) says so when they aren't:

  1. scripts/refresh-sidebar.sh has to be in cron (see Running it). "Did I favourite this?" is a question only an authenticated request can ask, and the token can't be shipped to a browser -- so cron reads the thread and writes public/comments.json, and the page renders from that. Without that cron job nothing new ever appears.
  2. The token needs read:statuses alongside write:statuses. On Mastodon that is a choice; on GoToSocial it is the only way comments work at all (see the note below). Reissue it under Preferences → Development if yours predates this: a token without it gets a perfectly good answer with the favourited field left out of it, which reads as "approved nothing". On Bluesky the existing app password is enough.
  3. You have to go and star the comments worth keeping -- see the warning above the list.

GoToSocial. Live comments cannot work there, whatever you configure: every read of a thread needs a token, all four of its authentication requirements are on, and a token cannot be put in a visitor's browser. Turn on comments.approval: fav -- the cron reads the thread with the token and only the replies you star reach the page. Two more things worth knowing: the token is made under Settings → Applications → New Application (not Preferences → Development, which is Mastodon's path and does not exist here), with the scopes written space-separated -- it needs read:statuses as well as write:statuses, and both fit in one token because GoToSocial has granular scopes. And a GoToSocial instance usually allows 5000 characters rather than 500, so mastodon.toot_length is worth setting to whatever your server's statuses-max-chars says. doctor --online checks the first of these for you and says so in one sentence.

Worth knowing before switching it on:

  • Approval is not instant -- up to one cron interval, and for a post older than ~90 days up to a week, since old posts are only refreshed occasionally. ./scripts/refresh-sidebar.sh --full does it now.
  • A favourite is public on both networks. Anyone can see which replies you starred, and replies starred in the past count as approved.
  • The side effect nobody asks for and everybody gets: with the thread already read server-side, the visitor's browser stops contacting the network at all, and the page's CSP drops its connect-src grant to it. Avatars are still loaded from the instance hosting them.
  • It keeps replies off the blog. It cannot remove them from the network, where the thread stays public and this site still links to it. Block, mute and report remain the tools for that.