Over at College Confidential we recently hired Student Ambassadors. As we perused the resumes, we noticed many candidates have computer science backgrounds. So I interviewed a few more people and we hired two more Student Ambassadors who will be focused on helping us improve our user interface.1 Now I'm like the teacher who is thrust into a new-for-them class and has to learn each lesson a week before teaching it. So let's jump into the world of Discourse theme development.

The first step is to read the documentation. It' not necessary to understand everything at one go, but it does help to have an idea of what a theme consists of and how to manage them on your own Discourse server.

Speaking of which, we're going to install Discourse locally so that we can make and test changes without breaking anything for other people.2 In my time at EDB I got initiated into the cult of Docker. It's amazing to be able to spin up an entire virtual machine with a few commands. Docker sidesteps all the complications of hunting down prerequisites for native installation.3

Installing Docker

Discourse has a terse set of instructions for installing Docker. I'd add a few notes:

Once you have Docker installed, it's probably a good idea to test it out so that if you have problems later you know it's not something basic related to Docker. (Trust me. This is still easier than a native install.)

A quick note on organization

We're going to do several git clone commands that pull down code from GitHub. It's pretty easy to get confused about where your working code is if you run these commands willy-nilly. So I've gotten in the habit of putting code that I intend to work on in ~/src. So from the command line, I start by creating the directory:

$ mkdir ~/src

(This only needs to be done once.)

And when I'm about to clone a repository, I move do that directory first:

$ cd ~/src
$ git clone https://github.com/some/repository

That way I can always find my work later on. If you ever clone something elsewhere, you can always move it later. Git repositories maintain their own context wherever you move them:

$ mv repository ~/src

Configuring Discourse

If you don't already have git installed, now is a good time to do that. Starting the container will take a few minutes, if all goes well. You'll know it worked if you visit http://localhost:4200/ and see "Congratulations, you installed Discourse!" Unfortunately, you won't have an admin account registered, so we'll need to do that. Those instructions are for Discourse hosted somewhere else, but we are using a local Docker. So from wherever you have the Discourse repository4 downloaded, run d/rake admin:create instead:

$ d/rake admin:create
Email:  jon@jlericson.com
Repeat password:  

Ensuring account is active!

Account created successfully with username jon
Do you want to grant Admin privileges to this account? (Y/n)  y

Your account now has Admin privileges!

[Probably use your email and not mine!]

At this point you have a local installation of Discourse! Take moment to bask in your own glory.

Note that you'll be running:

  1. The discourse_dev Docker container.
  2. d/rails s in a terminal.
  3. d/ember-cli in another terminal.

If you stop the container, the other processes will stop too. When you start it up again, you'll need to restart those processes.

Installing a custom theme

College Confidential's theme is in a private repository. For the sake of this post, I'm going to pretend that we are hacking on the Graceful theme. Anytime you see the string graceful below, substitute the correct string for the theme you are actually working on.

Begin by cloning the theme repository:5

git clone https://github.com/discourse/graceful
Cloning into 'graceful'...
remote: Enumerating objects: 283, done.
remote: Counting objects: 100% (123/123), done.
remote: Compressing objects: 100% (53/53), done.
remote: Total 283 (delta 76), reused 78 (delta 68), pack-reused 160
Receiving objects: 100% (283/283), 186.07 KiB | 1.11 MiB/s, done.
Resolving deltas: 100% (128/128), done.

At this point, you can use the zip command to zip up the directory and install the theme via http://localhost:4200/admin/customize/themes . But there's a better way! I recommend using the Discourse Theme CLI:

$ gem install discourse_theme
$ discourse_theme watch ~/src/graceful

The second command will prompt for a few bits of information:

  1. Use http://localhost:4200 for the URL when using Docker locally.
  2. Get an API key from http://localhost:4200/admin/api/keys . Make sure you:
    • Use a descriptive description so you remember what this key is for.
    • The key should be set for a single user—your admin user.
    • It should be Glocal scope.
  3. Go ahead and save your inputs so that you won't need do the whole process over again next time.
  4. Allow the script to create a new theme on your Discourse server.

Now if you change anything in theme directory, it automatically updates the theme. The only downside is that you'll need to have yet another process running:

  1. The discourse_dev Docker container.
  2. d/rails s in a terminal.
  3. d/ember-cli in another terminal.
  4. discourse_theme watch PATH in yet another terminal.

The plus side is you can use your favorite IDE6 to change the theme and see the results update live.

Previewing the theme

The discourse_theme script will give you some options on how to sync the theme. After the first time, you can choose to sync with an existing theme. That's usually the right choice unless you have some reason to have several themes with the same name on your test site. The command includes a few useful links to preview, manage and test your theme:

$ discourse_theme watch ~/src/graceful             
» Using http://localhost:4200 from /Users/jericson/.discourse_theme
» Using api key from /Users/jericson/.discourse_theme
? How would you like to sync this theme? Sync with existing theme: 'graceful' (id:7)
» Uploading theme from /Users/jericson/src/graceful
✔ Theme uploaded (id:7)
i Preview: http://localhost:4200/?preview_theme_id=7
i Manage: http://localhost:4200/admin/customize/themes/7
i Tests: http://localhost:4200/theme-qunit?id=7
» Watching for changes in /Users/jericson/src/graceful...

You can also navigate there via the menu bar:

  1. Admin or Settings
  2. Customize
  3. Themes
  4. The theme you are watching

Graceful theme setup page

Checking the "Theme is enabled by default" will set your site to use the new theme automatically. That's a good choice when working locally, but on a shared system you should use the "Preview" option at the bottom of the theme's settings page so that it doesn't change the theme for everyone.

Next time: Making changes and working with branches.


  1. It's similar to a paid internship, which how I got my start.

  2. We can use Oracle Cloud, but that's an unnecessary complication when the goal is to work on our theme.

  3. I even use Docker to preview posts for this very blog.

  4. Hopefully ~/src/discourse. Hint, hint!

  5. Don't forget to cd ~/src first! If already forgot, just move the graceful directory there.

  6. Visual Studio Code is a good place to start if you haven't got a favorite yet.