Schnack is an open source commenting system written in JavaScript.
- Tiny! It takes only ~8 KB!!! to embed Schnack.
- Open source and self-hosted.
- Ad-free and Tracking-free. Schnack will not disturb your users.
- It's simple to moderate, with a minimal and slick UI to allow/reject comments or trust/block users.
- webpush protocol to notify the site owner about new comments awaiting for moderation.
- Third party providers for authentication like Github, Twitter, Google and Facebook. Users are not required to register a new account on your system and you don't need to manage a user management system.
This is the fastest way to setup schnack.
Requirements:
- Node.js (>= v8)
- npm (>= v5)
Create a new folder in which you want to install Schnack:
> mkdir schnack
> cd schnack
Download the config file template as schnack.json
and edit it according to configuration section:
> curl -o schnack.json
> vim schnack.json # or open with any editor of your choice
Make sure you remove all plugin configs that you don't need. Then install Schnack and the configured plugins via
> npm init schnack
Run the server:
> npm start
Embed in your HTML page:
<div class="comments-go-here"></div>
<script src="https://comments.yoursite.com/embed.js"
data-schnack-slug="post-slug"
data-schnack-target=".comments-go-here">
</script>
schnack will try to read the configuration from the schnack.json
file. The minimal configuration requires the following fields: schnack_host, admins, oauth.secret and at least one oauth provider (id and secret key) and one notification provider.
The fields schnack_host and page_url should be hosted on the same domain. If your blog is running at https://blog.example.com, then your schnack instance should be reachable at any subdomain of example.com.
option | description |
---|---|
schnack_host | the hostname where the schnack server runs (e.g. https://schnack.example.com) |
page_url | the page where schnack is going to be embeded. The %SLUG% placeholder should be replaceable with you tags (e.g. https://blog.example.com/posts/%SLUG%) |
database | |
  comments | the filename of the embeded SQLite database where the user comments are going to be stored (e.g. comments.db) |
  sessions | the filename of the embeded SQLite database where OAuth session data is going to be stored (e.g. sessions.db) |
port | the port where the schnack server is going to run (e.g. 3000) |
admins | an array of userIDs which can login as admin (e.g. [1, 245]) |
oauth | |
  secret | the secret passed to express-session |
plugins | additional config options for plugins (see below) |
date_format | how to display dates (e.g. MMMM DD, YYYY - h:mm a) |
trust | a list of trusted users (see Trust your friends) |
schnack supports various authentication and notification providers which can be configured via plugins. Once you added the plugin config to your schnack.json
, they will be installed automatically via:
> npm init schnack
schnack uses authentication plugins to authenticate the users of your comment platform, in order to prevent spam without having to implement and manage an own user management system. Most of these plugins use external services as OAuth providers.
You should configure at least one authentication plugin in order to allow users to login and write comments.
When a user logs in through an OAuth provider, the session informations are stored into a cookie. In order to allow this action, your schnack instance and the page where you are embedding schnack should reside on subdomains of the same domain.
The secret
provided in schnack.json
will be used by express-session to sign the session ID cookie.
If you activate the plugin auth-mastodon
users can log in through any Mastodon instance account.
- All you have to do is to define
app_name
andapp_website
in theplugins.auth-mastodon
section of yourschnack.json
. Schnack will then create OAuth applications at Mastodon instances whenever a user tries to sign in (the users are asked to enter a Mastodon domain before signing in).
// schnack.json
{
"plugins": {
"auth-mastodon": {
"app_name": "your website name",
"app_website": "https://blog.example.com/"
}
}
}
If you activate the plugin auth-twitter
users can log in using their Twitter account.
- Create a new OAuth App on apps.twitter.com
- Name: the name of your blog
- Description: the description of your blog
- Website: the URL of your schnack instance (e.g. https://schnack.example.com)
- Callback URL: the URL of your schnack instance followed by
/auth/twitter/callback
(e.g. https://schnack.example.com/auth/twitter/callback) - Check the checkbox "Allow this application to be used to Sign in with Twitter"
- Copy the Consumer Key and the Consumer Secret from "Keys and Access Tokens" to
plugins.auth-twitter.consumer_key
andplugins.auth-twitter.consumer_secret
inschnack.json
// schnack.json
{
"plugins": {
"auth-twitter": {
"consumer_key": "xxxxx",
"consumer_secret": "xxxxx"
}
}
}
If you activate the plugin auth-github
users can log in using their Github account.
- Create a new GitHub OAuth App
- Application name: the name of your blog
- Homepage URL: the URL of your schnack instance (e.g. https://schnack.example.com)
- Application description: the description of your blog
- Authorization callack URL: the URL of your schnack instance followed by
/auth/github/callback
(e.g. https://schnack.example.com/auth/github/callback)
// schnack.json
{
"plugins": {
"auth-github": {
"client_id": "xxxxx",
"client_secret": "xxxxx"
}
}
}
If you activate the plugin auth-facebook
users can log in using their Facebook account.
// schnack.json
{
"plugins": {
"auth-facebook": {
"client_id": "xxxxx",
"client_secret": "xxxxx"
}
}
}
If you activate the plugin auth-google
users can log in using their Google account.
// schnack.json
{
"plugins": {
"auth-google": {
"client_id": "xxxxx",
"client_secret": "xxxxx"
}
}
}
When new comments are awaiting for approval, schnack can notify the administrators via notification plugins.
Web-push is a protocol designed to send push notifications to browsers on mobile and desktop devices. Using a Service Worker it is possible to register a component which is always listening for push notifications, even when the tab or the browser are closed. This allows to send end-to-end notifications from the schnack server to the admins.
In order to configure web-pushes, you should follow these steps:
- Generate a VAPID key pairs using the web-push package:
node_modules/.bin/web-push generate-vapid-keys
- Copy the VAPID keys in
schnack.json
// schnack.json
{
"plugins": {
"notify-webpush": {
"vapid_public_key": "xxxxx",
"vapid_private_key": "xxxxx"
}
}
}
- Add your user ID to the admin array in
schnack.json
- Copy the sw.js into your website's root path, so that this will be accessible at https://comments.example.com/sw.js
- Login to your schnack instance and you will be asked to grant the permission for push notifications.
When a new comment is posted, you will be notified with a notification. In order to avoid flooding, schnack will send only a notification every 5 minutes, highlighting the number of comments awaiting for approval.
We strongly reccommend to subscribe to push notifications using Chrome on your mobile device.
schnack can also send a message to a slack channel when a new comment is awaiting for approval. In order to configure this service just create a slack webhook and paste its URL to notify.slack.webhook_url
in schnack.json
.
// schnack.json
{
"plugins": {
"notify-slack": {
"webhook_url": "xxxxx"
}
}
}
PushOver is a service to send notifications to your devices. You can use it to receive schnack notifications. In order to configure it you should first register for an account and download a client. Then you can create an app and copy the token and the key to notify.pushover.app_token
and notify.pushover.user_key
in schnack.json
.
// schnack.json
{
"plugins": {
"notify-pushover": {
"app_token": "xxxxx",
"user_key": "xxxxx"
}
}
}
If you configure the plugin notify-sendmail
schnack will use your web servers sendmail
program to send an email to you every time a comment is awaiting your approval. Note that you may need to configure sendmail on your server before this is working.
// schnack.json
{
"plugins": {
"notify-sendmail": {
"to": "[email protected]",
"from": "[email protected]"
}
}
}
If none of the notification services fits your needs, you can still use the RSS feed provided at /feed
to stay updated about the latest comments posted. You can also use this endpoint in combination with services like IFTTT.
The language used in the Schnack form and comments ("Send comment", "Reply", etc.) can now be customized! Just pass any wording you want to change as data-schnack-partials-
attribute to the script tag:
<script src="https://comments.yoursite.com/embed.js"
data-schnack-slug="post-slug"
data-schnack-target=".comments-go-here"
data-schnack-partials-reply="Reply to this comment"
data-schnack-partials-sign-in-via="To post a comment sign in via">
</script>
Here's a list of all the supported attributes (make sure to add data-schnack-partial-
in to the keys:
key | default value |
---|---|
sign-in-via |
To post a comment you need to sign in via |
login-status |
signed in as @%USER% (<a class='schnack-signout' href='#'>sign out</a>) |
or |
or |
edit |
Edit |
preview |
Preview |
cancel |
Cancel |
reply |
Reply |
send-comment |
Send comment |
post-comment |
Write your comment here (feel free to use markdown). Please be nice :) |
mute |
mute notifications |
unmute |
unmute |
admin-approval |
This comment is still waiting for your approval |
waiting-for-approval |
Your comment is still waiting for approval by the site owner |
Administrators are managed adding or removing their schnack user ID to the admins
array in config.js
. When a user logs in as administrator, the moderation UI will appear in the certain comment section. By default it's set to [1]
. So the first user will be an admin.
It is possible to approve or reject single comments, but it is also possible to trust or block a certain user. An approved comment will be displayed to all users visiting your site, while a rejected comment will be deleted. Comments posted by a trusted users are approved automatically, while comments posted by blocked users will be automatically deleted.
schnack also prevents users from posting the same comment twice.
You can provide a list of user IDs of people you trust for each authentication provider. For instance, you could use the Twitter API to get a list of all the people you follow and drop that into the trust.twitter
in config.js
.
"trust": {
"twitter": [
"916586732845400064",
"902094599329591296"
],
"github": [
1639, 2931, 2946, 3602, 4933
]
}
The most effective way to keep a backup of your data is to take a copy of your comments.db
file, which is actually including all necessary data. If you cannot find this file then you probably set another name to database.comments
in schnack.json
.
It is possible to import disqus XML export and Wordpress XML export. In order to be able to import your comments, a database should already exist and schnack shouldn't be running. The importer requires Node.js >= v9.
You can export your data from Wordpress following this guide. Then you can run the following to import the comments into schnack's database:
npm run import -- wordpress.xml
You can export your disqus comments and import them into schnack running:
npm run import -- disqus.xml
You can build a Docker image for the schnack server running:
docker build -t schn4ck/schnack .
The image will contain everything in the project folder and can be started with:
docker run -p 3000:3000 -d schn4ck/schnack
In order to be able to edit your config file and your SQL database files, you may want to share the project folder with the docker container:
docker run -p 3000:3000 -v $(pwd):/usr/src/app -d schn4ck/schnack
Here you can leave us some comments. Let us know what you think about schnack!