npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jekyll-discuss

v1.0.0

Published

A commenting system for Jekyll

Readme

Jekyll Discuss

A commenting system for Jekyll

Introduction

Jekyll is a powerful blog-aware static site generator. Due to the nature of static sites, including dynamic content — in particular, user-generated content — on a page can be quite challenging. A typical example of that is a blog's commenting system. How to serve that content with an application that consists of pure static HTML files?

As I described in this post and, more in depth, in this post, there are several options to address this limitation. Third-party commenting platforms like Disqus are quite popular and easy to implement.

However, as explained by Tom Preston-Werner in this talk, that comes with the huge caveat of not hosting the comments data, taking away one of the great selling points of Jekyll — the fact that the entire data is hosted together in a repository, not scattered through a myriad of databases and servers.

Other approaches include the actual comments with the rest of the data, but require either a manual build or a complex Continuous Integration process. That makes the integration with GitHub Pages much more difficult.

So what is this?

Jekyll Discuss is a Node.js server-side middleman that handles comments as POST requests from a form, creates data files with its contents and pushes them to a GitHub repository. When using GitHub Pages, that will automatically trigger a build and the new data files will be part of the generated site.

Jekyll Discuss diagram

There was a previous iteration of this project written in PHP, which I'll no longer maintain.

Disclaimer

This project is still pretty much at a point where it's made to solve my specific needs — a commenting system to use with Jekyll, GitHub Pages and Mailgun. I'm always happy to make it as generic and flexible as possible, so please feel free to change it in any way you see fit and submit a pull request.

Installation

  1. Install via NPM

    npm install jekyll-discuss
    cd jekyll-discuss
  2. Edit and rename template config file

    vi config.template
    mv config.template config
  3. Start server

    node app.js

Configuration

Jekyll Discuss consists essentially of an Express server that handles requests, and a Bash script that pushes files to GitHub. Both of these components read information from a shared config file, which contains the following entries.

| Key | Mandatory | Description | |-----|-----------|-------------| | SERVER_HTTP_PORT | YES | Port to be used by the HTTP version of the Express server | | SERVER_HTTPS_PORT | No | Port to be used by the HTTPS version of the Express server | | SERVER_HTTPS_KEY | No | Path to the certificate key to be used by the HTTPS server | | SERVER_HTTPS_CRT | No | Path to the certificate file to be used by the HTTPS server | | SERVER_HTTPS_PASSPHRASE | No | Passphrase to be used with the HTTPS certificate | | COMMENTS_DIR_FORMAT | YES | Path and format of the comments directory (e.g. _data/comments/@post-slug) | | COMMENTS_FILE_FORMAT | YES | Path and format of the comment files (e.g. @[email protected]) | | GIT_USERNAME | YES | Username to use when pushing comments to GitHub | | GIT_TOKEN | YES | GitHub personal access token (info) | | GIT_USER | YES | GitHub user name | | GIT_EMAIL | YES | GitHub user email | | GIT_REPO | YES | Path to the local copy of the repository | | GIT_REPO_REMOTE | YES | Repository URL (.git) | | GIT_COMMIT_MESSAGE | YES | Message to be used on commits | | SUBSCRIPTIONS_DATABASE | No | Path to the file-based database used to manage subscriptions | | SUBSCRIPTIONS_NOTIFY_ALL | No | Email address to where notifications for all posts are sent | | MAILGUN_DOMAIN | No | Mailgun domain from where to send subscription notifications | | MAILGUN_KEY | No | Mailgun key | | MAILGUN_FROM | No | Sender name and email address for subscription notifications |

Usage

Submitting comments

Jekyll Discuss will be expecting POST requests containing the following fields:

| Field | Description | |-------|--------------| | name | Commenter's name | | email | Commenter's email address | | url | Commenter's URL (optional) | | message | Comment body | | company | Honeypot field for basic spam detection (info) | | subscribe | Whether to notify the commenter of future comments by email (must equal subscribe) | | post-slug | Post slug | | post-title | Post title | | post-url | Post URL |

Displaying comments

On the Jekyll side, showing comments for a post can be done simply by iterating through a set of data files.

Example:

{% if site.data.comments[post_slug] %}
	{% assign comments = site.data.comments[post_slug] | sort %}
	
	{% for comment in comments %}
		<div class="comment">
		  <h3 class="comment__author"><a href="{{ comment[1].url }}">{{ comment[1].name }}</a></h3
		  <p class="comment__date">{{ comment[1].date }}</p>
		  <img class="comment__avatar" src="https://www.gravatar.com/avatar/{{ comment[1].hash }}?d=mm&s=180">
		  {{ comment[1].message }}
		</div>
	{% endfor %}
{% endif %}

Email notifications

Jekyll Discuss can be used with Mailgun to send email notifications, allowing commenters to subscribe to new comments on any post. To do this, fill in the Mailgun related fields in the configuration file and edit the email templates that ship with the repo.

Here's an example (email-templates/new-comment.template.html):

<!-- New comment on Eduardo saying things -->
Hi {{ subscriber }},<br><br>

{{ commenter }} just commented on the post titled "{{ title }}" you subscribed to on <a href="https://eduardoboucas.com/blog">Eduardo saying things</a>.<br><br>

Click <a href="https://eduardoboucas.com{{ link }}">here</a> to see the comment or <a href="https://aws.bouc.as/jekyll-discuss/unsubscribe/{{ unsubscribe }}">unsubscribe</a> from future notifications.<br><br>

Best,<br>
Eduardo

The first line of the file, wrapped inside HTML comments, will be used as the subject of the email messages that use this template. The {{ subscriber }}, {{ commenter }}, {{ link }} and {{ unsubscribe }} placeholders will be automatically replaced by the values passed by the subscriptions module:

var data = {
	title: parsedData['post-title'],
	slug: parsedData['post-slug'],
	link: parsedData['post-url'],
	subscriber: subscription.name,
	commenter: parsedData['name'],
	unsubscribe: subscription._id
};

mailman.send('new-comment', subscription.email, data, function (body, error) {
	if (error) {
		console.log('[!] Error sending email: ' + error);
	}
});