Adding Mozilla/Coral Project Talk to Ghost

illustration by

This ended up being a really long post. You can skip the first half if you're not interested in what lead me to using Talk and get straight down to business under the Installing Talk heading.

I've been playing with all sorts of ideas lately for how to rebuild my blog. I did some playing around with Wordpress themes, but there's so much boilerplate, plus it's PHP which I rarely use these days. I put together a frontend in Vue using a Storyblok backend, but as my day job at the moment is very Vue heavy I decided that wasn't really pushing myself enough (because why make life easy for yourself, right?). I even started to build a statically generated, Markdown based blog in Gatsby as an excuse to learn some React, but it felt like too much "magic" and not enough coding for my liking, so I ditched that too.

Eventually, I stumbled across Ghost. I was searching for ideas as to what other small blog sites were using these days when I came across Ghost Pi, an excellent blog about one man's journey running a fully featured, Ghost based blog on a Raspberry Pi, and it just looked perfect. OK, I wasn't going to be coding something from the ground up like I'd started doing in some of my other attempts, but as a platform Ghost just looked great; simple, clean and flexible enough that I could write a completely custom front-end later on if I wanted to whilst maintaining the great editing tools Ghost has to offer. Throw in the stunning The Shell theme, and after about an hour of set up and a bit of theme tweaking (jazzing up the headers and adding a Google Amp theme) my new blog was ready to go.

However, there was still one key feature left to implement; a comment system. Now don't get me wrong, I'm not expecting my humble little blog to become a haven of high brow debate (I'd probably need to talk about something high brow for that to even remotely work) but one of the main reasons I put the time in to writing these posts is in the hope that someone, somewhere will stumble upon an issue I've already had, and rather than having to piece the solution together themselves and hit all of the same problems I did along the way, they might get a pointer in the right direction by skimming through my ramblings. And if that does happen, they might have questions or suggestions they want to contribute, so for that I need a comment system.

As usual, I started looking in to options for how I could implement this, and decided that rather than roll my own solution, I'd implement a tried and tested solution by someone else. Disqus is pretty much everywhere, but I'm really not a fan of polluting my site with ads. Facebook is another popular choice, but I'm not keen on the platform so I didn't feel great about using that. Eventually, I came across Talk, "an open-source commenting platform focused on better conversation" - perfect.

Installing Talk

The first step was to get a working copy of Talk installed locally. Initially, I thought I might build a copy from source, but in my new found "keep it simple" mindset I instead opted to set up a Docker container as described in the official Talk docs. This also involved installing Docker on my CentOS 7 server, which thankfully was really simple; following Docker's official guide, the install went off without a hitch. Make sure you don't miss the Linux post install page, as it includes some useful additional config that will make your life easier down the road.

The default docker-compose.yml that Talk provides is fine, but it doesn't specify the latest version. At the time of writing, Talk is on version 4.8.3, so modify the image line to specify it:

image: coralproject/talk:4.8.3

You'll also need to tweak a couple of settings for your environment. remember if this is going to be your live install you need to remove the NODE_ENV line. Set the TALK_ROOT_URL to an actual URL on your domain where you're hosting Talk (I used a subdomain for simplicity) and generate a random string (using something like LastPass Secure Password Generator) for your TALK_JWT_SECRET.

The next step is to bring your Talk install online with a docker-compose up -d - here's where I hit my first (tiny) hurdle. Following Docker's guide for CentOS 7, you don't actually install the docker-compose package. Thankfully, that's easily remedied by a quick yum install docker-compose. Once that's done, run docker-compose up -d again and you're on your way again.

While Docker is busy downloading and setting up everything Talk needs, you could take the opportunity as I did to go and add a record to your DNS to point at your new Talk on your chosen subdomain. I'm using NginX, so for me I just needed to add a simple config file to reverse proxy my Docker container:

server {
  listen 443 ssl http2;

  ssl_certificate /etc/letsencrypt/live/;
  ssl_certificate_key /etc/letsencrypt/live/;
  ssl_trusted_certificate /etc/letsencrypt/live/;
  include snippets/ssl.conf;

  access_log /var/log/nginx/;
  error_log /var/log/nginx/;

  location / {
    add_header X-Frame-Options "allow-from";
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header HOST $http_host;
    proxy_set_header X-NginX-Proxy true;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_redirect off;

If you're curious about that SSL snippet I've included, it's simply a list of recommended security settings for HTTPS sites that I ungraciously swiped from a Digital Ocean tutorial at some point. If anyone is interested, post in the comments and I'll append it to this post.

A couple of important thing to note about that NginX sample above:

  • the line add_header X-Frame-Options "allow-from"; if you're using X-Frame-Options (and you really should), then without setting this header correctly to allow traffic from your blog, Talk's scripts which we'll need to embed later aren't going to work
  • the lines proxy_set_header Upgrade $http_upgrade and proxy_set_header Connection "upgrade"; without them, Talk's script won't be able to open a websocket to your Talk backend, which allows it to live update comments as they come in without reloading the entire stream

Once all that config is done, restart your NginX server and navigate to https://<YOUR_TALK_DOMAIN>/admin/install to complete the installation process. There's nothing here that should trip you up, just follow the wizard and you'll be done in no time.

That's the core Talk install finished. There's a bunch of useful sounding plugins available, so check those out and add the ones you want. I'll likely make use of the Toxic Comments plugin and add some third party auth plugins. If any of that turns out tricky, I'll blog my experiences.

Adding Talk to Ghost

Now that you have Talk up and running on your server, you need to integrate the comments with Ghost. It's really easy to do, but you are going to need to edit your site's theme to do it. Thankfully, Ghost's handlebar themes are much simpler than some other common blog platform's themes [cough*Wordpress*cough] so it shouldn't be too difficult to work out what's going on even if you've never seen a Ghost theme before.

Download a copy of your current theme if you don't already have one (you can do this from your admin area, under the Design section), look for a file called post.hbs and open it in your favourite text editor.

I can't tell you exactly what you'll find because that's going to vary from one theme to the next, but you'll certainly see a section wrapped with {{#post}} and {{/post}} tags, as this is Ghost's way of interpreting which part of a theme should be used to render your post. Study this section, compare it with a post on your blog and work out a good spot to drop in your Talk comments.

Log in to your Talk site and head to the Configure tab, then look for the Tech Settings menu. On that page, you'll see a block labelled up as Embed Comment Stream with some code in it - this is the magic that will add Talk to your Ghost blog. Copy the block of code, then simply paste it in to your chosen position in your theme's post.hbs. It's not essential, but I'd recommend adding lazy loading. This way, your page load isn't slowed down by waiting for Talk's comments to load. In fact, the comments aren't loaded at all if your user doesn't scroll down far enough to see them. It's really simple to do; just add lazy: true to the options in the block of code Talk generated for you. My final code block looks like this:

<div id="coral_talk_stream"></div>
<script src="" async onload="
  Coral.Talk.render(document.getElementById('coral_talk_stream'), {
    talk: '',
    lazy: true,

Save, Zip your theme back up and then upload it to Ghost - it's going to warn you that you're overwriting an existing theme, that's fine.

If you head to one of your posts now (and scroll to the end of the post if you used Talk's lazy loading feature) then you should see a brand new comments box appear! Congratulations, you did it! However, out of the box it's quite likely that Talk sticks out like a sore thumb because it hasn't been styled to match your site. Let's sort that out next.

Styling Talk

CSS is a tricky one to advise on as it's going to be down to the way your Ghost theme is styled and how much you want Talk to integrate with that as to how you go about this.

In a nutshell, Talk helps you to target most elements it renders with a variety of CSS classes with the talk- prefix. There are also a bunch of styles that get added by another CSS bundle that Talk injects, which can interfere with the classes you're targeting. The easiest way to fix this is to simply make your CSS more specific. The entire Talk stream is wrapped in a div with the ID #talk-embed-stream-container, so one quick way of doing this is to simply make your CSS target the talk- classes within that container.

As Talk is rendered in an iframe, you can't simply add these styles to your theme's CSS as they won't target the contents of the iframe, so you'll need to make a separate CSS stylesheet and upload it somewhere publicly accessible. Since I've made a customised version of my site's theme anyway, I added the CSS to the theme so that it's be uploaded to my theme's assets directory and I could link Talk to that. It also meant I could leverage the SCSS colour variables from my theme to help keep things consistent. If you take this approach, the CSS will be available at https://<YOUR DOMAIN>/assets/css/<FILENAME>.css.

Once you've uploaded your CSS, head over to your Talk admin page, go to the Configure tab and Tech Settings and put the URL for your stylesheet in the Custom CSS URL box.

That's all there is to it. It might seem long winded, but in reality it probably took a couple of hours start to finish, really not bad at all. I was going to write up how to actually use Talk once it's all set up but honestly, it's so intuitive there's no need. Talk is even clever enough to automatically create new Stories (what Talk calls a comment stream) whenever a new blog post loads up the comment stream for the first time, and names them as per your post's title so it's really easy to see in Talk's admin page where all your comments are coming from.

Next on my agenda is implementing some of the plugins I mentioned earlier and writing up my experience in that respect.

In the meantime, head to the comments below if you have any questions for me 👍