Skip to content

ShinyCMS Developer Documentation

Writing a new plugin


Move into the base directory of your copy of the ShinyCMS code: cd ShinyCMS-ruby

Then, run the plugin generator: rails g shiny:plugin plugins/ShinyThing

(Currently your plugin must be named Shiny{Something} for some filepath-dependent hacks to work.)

The plugin generator is a cut-down version of the standard Rails Engine generator (rails new plugin --mountable) with some added boilerplate to fit the resulting plugin into ShinyCMS. You can pass it flags which the rails plugin generator understands, to skip features that your plugin doesn't need - e.g: rails g shiny:plugin --skip-action-mailer --skip-action-mailbox --skip-action-cable plugins/ShinyThing


You should put the appropriate details in plugins/ShinyThing/shiny_thing.gemspec, and you'll probably want to edit plugins/ShinyThing/ as well.


Your tests go in plugins/ShinyThing/spec/ and you can run them from the ShinyCMS root directory:

rspec plugins/ShinyThing  # to run tests for just your new plugin
rspec spec plugins  # to run tests for the main app and all plugins


Most of your code probably goes in plugins/ShinyThing/app/, with routes and locale files in plugins/ShinyThing/config/

Special files

Some special files are looked for and (if they exist) loaded as specified below, to help your plugin hook into the CMS:

Views (partials): * ShinyThing/app/views/shiny_thing/menu/_section.html.erb will be rendered as a new section in the main site menu * ShinyThing/app/views/shiny_thing/profile/_content.html.erb will be rendered in the 'content posted by this user' section of the user's profile page, if the ShinyProfiles plugin is loaded * ShinyThing/app/views/shiny_thing/search/result/shiny_thing/_model_name.html.erb will be rendered when content from your plugin appears in the search results, if the ShinySearch plugin is loaded and you have hooked your models into it * ShinyThing/app/views/shiny_thing/admin/menu/_section.html.erb will be rendered as a new section in the admin area menu * ShinyThing/app/views/shiny_thing/admin/menu/_other_item.html.erb will be rendered as an item in the Other section of the admin area menu * ShinyThing/app/views/shiny_thing/admin/toolbar/_section.html.erb will be rendered in the admin toolbar

Helpers: * Methods in ShinyThing/app/helper/shiny_thing/MainSiteHelper.rb will be available to all main site views, not just those rendered by your plugin's controllers


ShinyCMS uses a gem called Packwerk to check on coupling across architectural boundaries.

The short version is that you should only be using interfaces exposed as public by other plugins that you have explicitly declared a dependency on, rather than 'reaching into the middle' of other plugins or depending on them unexpectedly.

The core ShinyCMS plugin has quite a lot of exposed interfaces for your plugin to leverage; base controllers you can inherit from, concerns and helpers you can use, etc etc. You can find all of this code in its app/public directory. Most other plugins will have far less public code exposed, as the idea is to keep them independent of each other as much possible, so that people only have to enable the ones that they want to use for a particular site.

Packwerk uses package.yml files in each plugin to know what is and isn't inside its boundaries, and which other plugins it explicitly depends on (for example, ShinyNewsletters depends on ShinyLists).

The command bin/packwerk validate will check to make sure those package.yml files are all syntaxually valid, and the command bin/packwerk check will check the boundaries and report any violations it finds. Typically these are when code in one plugin directly accesses a class or module from another plugin without declaring a dependency on that plugin, or accesses a class or module that the other plugin has not made public.

Share and Enjoy!

If possible, please share your plugin with other ShinyCMS users, by making a PR back to the main ShinyCMS-ruby repo on GitHub! :)