Developer Notes

Bolt Comments

Introducing Bolt Comments

While rebuilding my blog I ventured into the world of Jamstack. It's an interesting ecosystem but .NET presence is sorely lacking. So I did my part and built an integration between Statiq, a .NET Static Site Generator, and Kontent, a headless CMS with excellent .NET support. 

Next up was adding comments. I was fully expecting there to by a range of open source solutions, but there isn't really. At least not anything I'd be comfortable either signing up for or hosting myself.

And... there definitely isn't anything .NET or Azure based. So I ended up rolling my own and called it Bolt Comments.

Requirements

  • Privacy : I don't want to subject people on my site to 3rd party tracking. 
  • Technology : preferably .NET / Azure based, because that's what I know best
  • Cheap : This is a personal site and... I'm Dutch, so obviously, cheap is important.

About privacy

I really don't like ads and absolutely do not want visitors to my site to get hooked and followed around. So no 3rd party tracking is allowed on this site (apart from the essential analytics of course). This already crosses off any major player in the commenting space like Disqus.

Inspiration

I looked around for similar open source projects and came across a Netlify project Jamstack Comments Engine. I really liked the simplicity of it, though it's not suitable for production usage imo. It is a pretty good hint at what a solution should look like.

That solution uses Netlify functions and stores it's data in Netlify forms. Azure has had Functions for quite a while, so I started scaffolding an API based on functions. The cheap and easy way to store data with functions is Azure Storage Tables. So I went with that. There are some nice bindings that work well with Storage Tables so that got me off to a good start.

Azure Static Web Apps

At some point I figured I needed an admin UI for this. I really wanted to make a nice looking app with decent UX so I decided to go for a React app. I know a fair bit of React and was looking forward to giving functional components a proper try.

Around the same time Azure Static Webapps was nearing completion and it's a pretty good fit for this project. It provides hosting for single-page apps and HTTP functions. It's pretty similar to Vercel and Netlify, but runs .NET code for the API code.

Bolt comments screenhsot
Bolt comments screenhsot

Connectivity

To make Bolt Comments really useful it needs to connect it to the outside world. When a new comment is posted I want to be notified. And since I'm using static static site generation to build this site, I want regenerate the site when comments are published. To limit complexity and integration points, I've added support for web hooks to handle these events.

Webhooks enable workflow services to trigger and send an e-mail provider or integrate with collaboration tools like Teams or Slack. Service like ZapierITTT or Pipedream make this really easy and are cheap too.

Bolt comments - web hook settings
Bolt comments - web hook settings

Security

Any app needs to be able to take some amount of abuse these days. Comments are essentially user contributed content, which means I need to be extra careful.

The easy catch is not to accept any <script> tags. So that'll just be rejected. 

After some testing and playing around I decided to implement filtering on the posted comment to strip out tags that are outright dangerous or that can destroy your site layout.

In a nutshell, any content is first pulled through a Markdown processor to turn markdown into HTML. Then the HTML is filtered and purged. That is converted back to Markdown and stored.

Markdown inside

Even though comments are stored as Markdown internally, you get both Markdown and HTML in the API when you fetch comments. This allows both easy API integration (just stream the HTML into your app) and more flexible processing with a static site generator.

Auth

Authorization for the admin UI is handled by Azure Static WebApps. It provides easy self-managed auth using the most common login providers.

API calls to post or fetch comments also support an API key. That key is managed through the admin API. 

Bolt comments - api key settings
Bolt comments - api key settings

Note thought that Azure Static WebApps currently do not support CORS for anything other than the static site itself. So when invoking the Bolt Comments API directly from a site, there has to be some sort of proxy to make the API call for your site. 

Most Jamstack platforms offer a nice way to do that, for example Netlify has proxies that can inject the API key so you don't have to share that in your application.

Deployment

The holy grail to adoption of any software project, especially for open source, is how easy it is to get started. For a cloud project like Bolt Comments that means it should be dead simple to spin up an instance.

Unfortunately, this is where Azure Static Web Apps does not quite level up to competitors like Vercel and Netlify. Right now some manual steps are required but hopefully that'll change soon.

Conclusion

So I want something that's easy to host and safe for my visitors. I had a lot of fun building the app with Azure Functions and Azure Static Web Apps. If you're looking for a place to host your comments, please take Bolt comments for a spin and let me know what you think by leaving me a comment!