Comments on a static site without any third-party services (but you do need postgres lol)

When I was looking for a way to implement comments on my fic archive, I found some instructions for using Discord webhooks to do so; it wasn’t this post but the vibe was similar. Using the method described, one sets up a private server and configures a webhook to post messages to a certain channel, and then one can include some JS on one’s site that sends a POST request to the webhook URL containing text captured in a form. It’s cleaner than a lot of alternative services and doesn’t require embedding any non-customisable cringe on one’s own site, and I used it for some time without any trouble.

But this still involves passing data through someone else’s server, and I was keen to delete my Discord account during the Great Account Deletion of 2024–5, so I was keen to find a way to replace this method. Eventually I came to a simple realisation: the POST request doesn’t have to go to a Discord webhook. It can in fact go to anything that accepts a POST request. It can go to a GoToSocial account.

I installed GoToSocial on the VPS in September 2024 to replace Pleroma as my fediverse instance of choice; it’s very lightweight and extremely robust. Like other fediverse software, GTS provides an API that allows posting from other sources as long as the user is in possession of an account-specific access token (the instructions for generating these are extremely convoluted and I kind of love that ngl). Posting to a GTS account can therefore be done by sending a POST request to the API. So using the general method for sending to Discord webhooks from a static site, we can swap out the Discord URL for the GTS API endpoint and include the access token, and then the content of whatever has been put into the form will be posted as a status by that account. I set up a specific GTS account to receive these form submissions, set it to manually approve follow requests and to post all statuses as followers-only, then approved only my own main account as a follower. So if someone posts a comment on any of my fics (and on some other pages on my site now that I’m starting to implement this elsewhere), that comment will show up in my fediverse feed but can’t be seen by anyone else until I manually post it on my site.

Like every weird workaroundy tech thing, this of course has some disadvantages:

Implementing this system on a given page in its most basic incarnation just needs two components, the first being the comment form:

<form id="theform" onsubmit="sendContact(event)" class="jsonly">
  <input type="text" id="nameInput" required placeholder="Name">
  <textarea id="messageInput" rows="5" maxlength="4800" required placeholder="Comment"></textarea>
  <button type="submit">Submit</button>
</form>

and the second being the JavaScript that makes the API call:

<script>
  async function sendContact(ev) {
    ev.preventDefault();
    const thePage = window.location.href;
    const senderName = document.getElementById('nameInput').value;
    const senderMessage = document.getElementById('messageInput').value;
    const gtsUrl = 'https://{GoToSocial URL}/api/v1/statuses';
    const response = await fetch(gtsUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
	'Authorization': 'Bearer {access token}',
      },
      body: JSON.stringify({'status' : 'new comment on ' + thePage + ' from ' + senderName + '\n\n' + senderMessage}),
    });
    if (response.ok) {
      alert('Comment submitted!');
      } else {
      alert('Comment failed to send for some reason!');
    }
    document.getElementById("theform").reset();
  }
</script>

I also like to hide the comment form and replace it with an apologetic message for anyone who has JavaScript disabled; I do this by adding <noscript><style>.jsonly{display:none;}</style></noscript> to the page head and then putting the jsonly class on the form element, and then adding something in its place using <noscript>. I think I picked this one up from the Fandom Coders discord server, back when I used Discord, lol.

Comments

You can comment on this post if you like. Comments will be posted below after moderation.