Fetching contributors…
Cannot retrieve contributors at this time
178 lines (135 sloc) 6.12 KB


Caloris is Web Content Management System built as a Rails 3.x Engine.

Rather than relying on a database, a git repository provides persistence, enabling revision history and release control. Content can be managed like source code, can be branched, merged, and different versions can be served and edited. Content and extensible, embedded metadata are valid HTML markup in a single file per page.

Coupled with in-place editing by Mercury Editor, content managers can provide easy-to-use, controlled editing to a wide user base, while maintaining ultimate control of the content and release to production.

Support for multiple users is supported via git branches. While content is served from a specified branch, editors can view content from any branch or commit, and can create their own branches to which changes are saved.

Etymology: The Caloris Basin, an impact crater on the planet Mercury, is one of the largest in the solar system.


A CMS for Rails should:

  • Be an Engine, so that you do not have to build your app around it, nor change the way your app works
  • Be simple until a more complex site warrants something different
  • Leverage existing tools and concepts, i.e. git for version control
  • Be powerful for the technical, while remaining easy to use for the rest


Mainly inspired by the Mercury Editor.

The author was discouraged buy a high complexity-to-performance ratio of available Rails CMS approaches. Mercury Editor has a great philosophy: provide a great front-end rather than to create an end-to-end solution that might not be useful in all cases. Caloris is attempt to take over where Mercury leaves off to provide a solid back-end that will meet many needs without being overly complex nor limiting.


  • Revision and release control
  • Easy editing via filesystem and/or in-place front-end
  • Extensible in-markup metadata
  • Publishing control
  • Browsing of all history/revisions
  • Semi-automatic site-map generation


Most development has focused on the use of git for page storage, but the design should allow for other methods, such as database-backed stores, or a standard file-directory structure.

The git layer sits on top of a filesystem-based layer, adding branch, revision, and low-level commit functionality. Users create branches for editing, and the system creates commits using low-level routes that do not disturb the HEAD reference. This means edits can be made with effects to a live production site.


For an example application, check out test/test_app.

Place something like the following in lib/caloris.rb

# This cannot be an initializer: sites needs to be set up in all groups (i.e. assets as well)
# so that rake assets:precompile doesn't require initialize_on_precompile to be true for best performance.

require 'caloris'

Caloris.configure do |config|

  config.sites << do |config| = {git: {branch: Rails.env.to_s}} = 'www'
    if Rails.env.development?
      config.root = File.expand_path('../cms_content', Rails.root)
      config.root = File.expand_path('cms_content', Rails.root)
    config.default_page_template = 'plain'
    config.cache_enable = proc { |controller, page| Rails.env.production? }
    config.metadata_schema = {
        page_information: {
          page_id: :string,
          page_name: :string,
          template: :string,
        meta_tags: {
            description: :string,
            keywords: :string
        publishing: {
            published: :boolean,
            published_at: :datetime


module Caloris
  module Authentication
    def authenticate!

  module Authorization
    def can_update?

Deployment with Capistrano

Create or clone a git repository within the shared/ directory on the destination server. Check out the branch you intend to serve on that instance, i.e. a production branch. Configure your app, per environment, to point to the correct location for content, or symlink it after deploy:finalize_update.

Even while the server is running, you can update the repo and Caloris will pick up the new content. Simply pull or fetch/merge the new content and it will begin being served.

Your recipes might look something like:

namespace :cms_content do

  set :cms_content_path, proc { "/var/www/#{application}/#{rails_env}/shared/cms_content" }

  desc "Link to CMS content"
  task :link, :except => { :no_release => true } do
    run "rm -f #{latest_release}/cms_content && ln -s #{cms_content_path} #{latest_release}/cms_content"
  after "deploy:finalize_update_extended", "cms_content:link"

  desc "Update cms content to latest pushed commit. ** server must be restarted to pick up new assets."
  task :update, :except => { :no_release => true } do
    run <<-CMD
      cd #{cms_content_path} &&
      git pull origin #{rails_env}
  after "cms_content:update", "deploy:assets:precompile"


Assuming you're using the Asset Pipeline and fingerprinting, the server will capture those fingerprints and will continue to reference them until restart. You'll need to restart your server if you've updated assets.


  • Fix HTML entity conversion on save
  • Implement back-end for dialog-based metadata edit
  • Publish time support
  • Ensure all content is loaded (i.e. caloris_render_partial) per correct git ref
  • Caching, including coherence when HEAD is updated
  • Get page metadata update function working
  • Lint checker
    • Dead links
    • Design rules, i.e. no trailing slash on links


Developed by Doug Puchalski with the support of PENSCO Trust Company.

Inspired and made possible by Mercury Editor.


Distributed under the MIT License, copyright (c) Doug Puchalski.