Free and open-source comments for Hugo

Hello there,

today I discovered a new candidate for comments on Hugo: Cusdis

I was searching for an easy and open-source solution, I’m convinced.

Here is an overview :

Key features:

  • open source
  • lightweight (5kb)
  • hosting is available for free - Cusdus can also be self-hosted
  • easy to set up: no Heroku, no Github, no database required :sunglasses:
  • adding a comment does not require an account
  • available in several languages
  • moderation, dashboard
  • email notifications
  • nested comments
  • installed in 15 minutes

Installation

Create an account on Cusdis.com

Get your token and use it in the field data-app-id below

Add this code to your footer. For me, it was in layouts/_default/single.html

      <!-- Comments by Cusdis -->
      <h4>Comments:</h4>
      <div id="cusdis_thread" data-host="https://cusdis.com"
        data-app-id="See your dashbord on Cusdis"
        data-page-id="{{ .File.UniqueID }}" data-page-url="{{ .Permalink }}"
        data-page-title="{{ .Title }}"></div>
      <script async defer src="https://cusdis.com/js/cusdis.es.js"></script>

(Reminder: you need to edit data-app-id)

Done!

Demo

A demo is available at the bottom of the documentation for example

You can see it running with Hugo on roneo.org

Limitations:

  • no notification to an original poster when an answer is published. Bug report #78
  • no way to display the comment count next to the summary of an article. On the roadmap, see #109
  • no way to add a reaction (emoji) to a comment. See #58

Comparison with other tools

  • Disqus is a privacy nightmare
  • Staticman requires a complex setup of Heroku or another service
  • Uterrances requires an account on Github to post a comment

To help you remember the name: the name cus·dis comes from dis·qus. You got it?

10 Likes

Thanks a lot for recommending this. I have implemented it in my website (blog post example here), including translations like this. Very happy with it so far!

1 Like

highly recommended

1 Like

@iaeiou I’m using a Multihost setup in my site and I’ve noticed that, for a given blog post for example, all translated pages, even though they have a different .Permalink (thus different data-page-url), they share the same .File.UniqueID, so that the data-page-id is the same and comments made on one of the pages show up in all translated pages. Do you have an idea how can I solve it?

Here you can see a page where this has happened:

In those pages, the comment in English was made from the English version, and the Spanish one from the Spanish page, but all comments show in all pages because as I say the .File.UniqueID is the same regardless of the language.

I’d appreciate any help. Thanks in advance!

Rodri

Hi @alcarazr,

I found this reference in the forum Create a custom id for each post - #6 by Jura - I apparently already struggled with a similar issue (can’t remember in which context exactly) and used .File.UniqueID… My researches ended there at this time

A solution may be to concatenate this .File.UniqueID with another variable to minimize the risk of collision.

If anyone wants to have a look, the template of @alcarazr is here fisiquimicamente/cusdis.html at 524f439a6db0d6770863389c5b849f4916a8a8f2 · rodrigoalcarazdelaosa/fisiquimicamente · GitHub

Keeping in mind that some variables may vary on purpose, like the file name or post Title. The comments must land in the same queue despite such modifications

At some point we needed an immutable unique ID for each markdown file, so we placed this in the archetype:

uid = "{{ md5 (printf `%d%s%s` now.UnixNano .File.Path (getenv `USERNAME`)) }}"

Which produces something like:

+++
uid = "48ac3ee34ac60f3879b2f303843dd7ab"
+++

Yes, this exposes the unique ID in front matter, but the ID remains the same regardless of future changes to file path, title, content, etc.

2 Likes

I’m not sure how this can help me with my problem. Is there a way I can associate a really unique ID to each of my pages? The problem arises with translations, where each page shares the same path and file name, just changing the folder containing it.

Thanks!

It won’t, unless you create every page in every language with hugo new.

1 Like

I think page slug is a good choice in this case.

For now I’m going to solve it appending the language code like this:

data-page-id="{{ print .File.UniqueID .Site.Language.Lang }}"
1 Like

I updated the original post to point to the relevant issues on Github.

(thank you @alcarazr for asking for the feature “comment count”!)

1 Like

It seems to be possible to show comment count now: Cusdis Documentation

1 Like

Already implemented it in my website. Example here:

Relevant code here:

💬&nbsp;<span data-cusdis-count-page-id="{{ print $page.File.UniqueID site.Language.Lang }}">0</span>
<script defer data-host="https://cusdis.com" data-app-id="b9b5c1f3-2af7-4ef5-9d26-4c2b44a1d829" src="https://cusdis.com/js/cusdis-count.umd.js"></script>
2 Likes

That was fast!
Is it the same piece of code on the post list and in the single article view?

Yeah, both share the same page_metadata.html partial.

1 Like

Has anyone used this ? - GitHub - gitalk/gitalk: Gitalk is a modern comment component based on Github Issue and Preact.

I apparently already struggled with a similar issue (can’t remember in which context exactly) and used .File.UniqueID… My researches ended there at this time

A solution may be to concatenate this .File.UniqueID with another variable to minimize the risk of collision.

1 Like

Instead of using a partial, Cusdis comment form can be inserted with this shortcode:

{{- /* Comments with cusdis.com */ -}}

{{ if .Site.Params.CommentsCusdisID }}

    <div id="cusdis_thread" data-host="https://cusdis.com"
      data-app-id="{{ .Site.Params.CommentsCusdisID }}"
      data-page-id="{{ .Page.File.UniqueID }}"
      data-page-url="{{ .Page.Permalink }}"
      data-page-title="{{ .Page.Title }}">
    </div>
    <script defer src="https://cusdis.com/js/widget/lang/fr.js"></script>
    <script async defer src="https://cusdis.com/js/cusdis.es.js"></script>
{{end}}

{{- /* Comments area end */ -}}

All credits to jmooring