Beginner's Guide to Creating Discourse Plugins Part 1: Creating a basic plugin

Building a plugin in Discourse can be really simple, once you learn a couple of quirks. The goal of this post is to create a skeleton plugin and introduce you to the basics.

Your development environment

Make sure you have a development environment of Discourse running on your computer. I recommend you use the appropriate setup guide and come back when you’re done.


:tada: Update August 2018, see Rails plugin generator to create a complete discourse plugin skeleton in your plugins directory :tada:

When Discourse starts up, it looks in the plugins directory for subdirectories containing a plugin.rb file. The plugin.rb file has two purposes: it is the manifest for your plugin with the required information about your plugin including: its name, contact information and a description. The second purpose is to initialize any ruby code necessary to run your plugin.

In our case, we won’t be adding any ruby code but we still need the plugin.rb. Let’s create the directory basic-plugin with the file plugin.rb inside it, with the following contents:


# name: basic-plugin
# about: A super simple plugin to demonstrate how plugins work
# version: 0.0.1
# authors: Awesome Plugin Developer

Once you’ve created this file, you should restart your rails server and the plugin should be loaded.

An important Gotcha!

If you’re used to regular rails development you might notice that plugins aren’t quite as nice when it comes to reloading. In general, when you make changes to your plugin, you should Ctrl+c the server to stop it running, then run it again using bundle exec rails server.

My changes weren’t picked up! :warning:

Sometimes the cache isn’t cleared fully, especially when you create new files or delete old files. To get around this issue, remove your tmp folder and start rails again. On a mac you can do it in one command: rm -rf tmp; bundle exec rails s.

Checking that your plugin was loaded

Once you’ve restarted your rails server, visit the url /admin/plugins (make sure you’re logged in as an admin account first, as only admins can see the plugin registry).

If everything worked, you should see your plugin in the list:

Congratulations, you just created your first plugin!

Let’s add some Javascript

Right now your plugin doesn’t do anything. Let’s add a javascript file that will pop up an alert box when discourse loads. This will be super annoying to any user and is not recommended as an actual plugin, but will show how to insert Javascript into our running application.

Create the following file:


export default {
  name: 'alert',
  initialize() {
    alert('alert boxes are annoying!');

Now if you restart your rails server, you should see “alert boxes are annoying!” appear on the screen. (If you did not, see the “My Changes weren’t picked up” heading above).

Let’s step through how this worked:

  1. Javascript files placed in assets/javascripts/discourse/initializers are executed automatically when the Discourse application loads up.

  2. This particular file exports one object, which has a name and an initialize function.

  3. The name has to be unique, so I just called it alert.

  4. The initialize() function is called when the application loads. In our case, all it does is execute our alert() code.

You’re now an official Discourse plugin developer!

More in the series

Part 1: This topic
Part 2: Plugin Outlets
Part 3: Site Settings
Part 4: git setup
Part 5: Admin interfaces
Part 6: Acceptance tests
Part 7: Publish your plugin

Beginner's Guide to Creating Discourse Plugins Part 2: Plugin Outlets
Beginner's Guide to Creating Discourse Plugins Part 3: Custom Settings
Beginner's Guide to Creating Discourse Plugins Part 5: Admin Interfaces
Beginner's Guide to Creating Discourse Plugins Part 4: Git Setup
Beginner’s Guide to Creating Discourse Plugins Part 6: Acceptance Tests
Beginner’s Guide to Creating Discourse Plugins Part 7: Publish your plugin
How to start building stuff for Discourse if you're newbie (like myself)
Connecting to database with a plugin
Plugin API documentations?
How to create a new plugins?
Separating View from Data, Plugins, Modularity
How do you learn to build Discourse plugins?
Categories Topic Replies
How do you learn to build Discourse plugins?
Beginners Guide to Install Discourse on Ubuntu for Development
Overwriting controllers in plugin
Create fully custom header
Added custom initializer
Plugin Tutorial #1 - How to manipulate the text in the composer?
Beginners Guide to Install Discourse on macOS for Development
Customizing handlebars templates
How to properly display jalali dates for Persian language
Topic Ratings Plugin
Enable Like-Button for not logged-in visitors
Why do I need a block storage?
Custom Field not working
Redirecting old forum URLs to new Discourse URLs
Rails plugin generator
Why GNU License?
Code reading help. ES6, plugin-outlet `_connectorCache`, custom-html `_customizations`, appEvents
Customizing handlebars templates
Application Files after Digital Ocean Setup
Application Files after Digital Ocean Setup
Application Files after Digital Ocean Setup
Make an external http request from discourse
Specify user by external id
How can I make my own Discourse plugins?
Reputation and level on member profile
Dev Category sidebar
Plugin Documentation Style Guide
Any options for over-riding the username restrictions?
How would updating effect custom overrides?
How to Contribute to Discourse
I would like to change the template completely
Rails plugin generator
Creating a plugin
Fatal: Not a git repository (or any parent up to mount point /discourse)
Fatal: Not a git repository (or any parent up to mount point /discourse)
Adding command line tools support for user api keys
Store pdf and doc files as raw text in the database - Where to start?
Plugin routing problems
[PAID] Mentorship needed
Plugin API documentations?
Insert tag based upon word match
Place for total coding beginners to learn how to customise?
Custom navigation way Classified fillter
Add additional button post menu
The Ignore User feature (now in 2.3.0.beta7)
Create Custom APIs
How to make only a group of users can send messages to staff
How might we better structure #howto?
Theme-Component v Plugin: What's the difference
Creating Parsing Extensions
Automatic Welcome Message To New Users
How can I customized my own site
All latest images in posts from a category
Discourse Encrypt (for Private Messages)
Discourse Encrypt (for Private Messages)
(Ruby) Selecting only posts that are made by non-original posters
Notification when added to a group
Hosting discourse on our infrastructure AWS
Calling Python scripts w/ arguments on the backend via plugin?
How to add custom fields to models
What could cause a user to have another user's session?
Bot writer's tip: Processing every post
Overriding user_guardian.rb in a plugin (no fork necessary!)
Discourse Code Modification for personal use
Customizing CSS via plugin
Discourse Development Contribution Guidelines
About the Plugin category
About the Plugin category
Visual diagraming to add visual dimension to Conversations?
Custom Onebox engine
Allow reply-to individual instead of topic/forum (mailing list feature)
Adapt github changes to my own site
Push to digital ocean from command line and rebuild
How can I add "dislike" button?
How to convince my university to use/install Discourse?
Send Email to User When Mentioned
Hack to enable invitations for Trust level 1 users
Dropcaps in Discourse - cannot override span tag
Getting certain posts to Zapier
Plugin: add a menu icon (next to search)
Error When creating custom plugin
Error When creating custom plugin
IOTA as a currency for Discourse
New columns in directory (/users)
Bootstrap fails when plugin file specifies gem version range
Running my own discourse image
How to add a job to cron/anacron when creating Docker container
How to transfer data from plugin to app/views templates?
Which files can you override from a plugin?
Hide features for non-admin users through plugin

Thanks for this plugin guide.
I appreciate it and hope to see many more soon.
I really do.
In fact, I tried it and it worked great!

So, no offense intended, … … …

I would like to suggest one small change for those not masochistically inclined :ambulance:

//    alert('alert boxes are annoying!');
    console.log('console logging is not annoying!');

I considered console.log but I didn’t want to have to explain “open your dev console” too :smile:


Great guide - we tried it today and worked perfectly :smile:


Thanks for the guide. I expected it to be complicated, but it looks pretty simple! I’m looking forward to having a play around with plugin development! :smiley:

Is there anything more to the JS integration? Are there any other supported functions other than initialize?

You’ve whet my appetite! I’d love to see something more in depth.

I followed the instructions to set up my development environment, and I now have my system ready to go.

I just don’t know how to log into this system now…

Any advice on getting set up with my first admin user would be much appreciated.

Try these


That was absolutely it! Thank you very much for that!

Running rake admin:create was absolutely what I wanted.

1 Like

Thanks for the guideline

I followed these instructions and was not able to get the alert box to show up on my site.

I can view the plugin from the Admin panel, but after restarting my container there is no alert box that shows up. I have also tried console approach instead of using an alert, but have not had any luck. I have double-checked for typos, but haven’t found any.

Is this tutorial outdated?

Anything here we need to update @eviltrout?

1 Like

Are you trying to use this guide in production? Because it is meant to be used in a development environment as a way of creating plugins. The reason I ask is you said container which is how we host discourse in production mode.

In production, you have to have a plugin installed using git clone commands.


This makes sense then. I am running Discourse in production mode, and have previously installed plugins by adding git clone commands to the .yml file. I’ll try to get a development environment going and see if I have success.

Ok, so I FINALLY got a development instance of Discourse running, but I am still unable to see the alert box. Again, I have checked to make sure I didn’t make any typos in the path name or in the code itself. After creating alert.js.es6 I ran ‘bundle exec rails s -b’. The site is still accessible through the browser, but no alert box. I can see the plugin in the admin panel, but it is only in black text; unlike the rest of the plugins which are in blue.

I am a Discourse/Rails newbie so I apologize if I am making an obvious mistake.

Can you push your code to Github and link it here? Otherwise, it’ll be hard to see what is going wrong :slightly_smiling:

Did you try the impotrant gotcha referred to here?

1 Like

I thought I tried clearing out the /tmp directory, but when I tried it a second time it worked. For the record though, bundle exec rails s does not start the server on my instance. I have to run bundle exec rails server -b in order to get the instance to serve pages.

1 Like

I also cannot get the alerts to load. Here’s a link to the repo with the plugin, nothing else has changed besides the plugins folder.

Did you nuke the tmp directory and restart rails?

I got to page 5 before issue popped up.

Yeah I’ve nuked it almost every single time. What do you mean you got to page 5 before the issue popped up?

1 Like