The project is in a healthy, maintained state
Comfy Middle Seat is a Rails 7.2+ CMS engine.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

~> 1.0, >= 1.0.5
~> 4.0, >= 4.0.0
>= 2.1, < 4.0
~> 1.2, >= 1.12.2
~> 1.2, >= 1.2.2
~> 2.4, >= 2.4.0
~> 0.4, >= 0.4.3
>= 4.12, < 6.0
>= 7.0.0
>= 6.0.0
 Project Readme

Rails CI Test Coverage Gem Version Gem Downloads GitHub Release Date - Published_At

Comfy Middle Seat

A self-hosted, embeddable CMS engine for Rails 7.2+, 8.x

Add editor-managed pages, reusable layouts, rich text, Markdown, files, translations, search, and revision history to an existing Rails application—without moving your content into a separate service.

Comfy Middle Seat is actively maintained and continues the lineage of Comfortable Mexican Sofa and Comfortable Media Surfer. It keeps the memorable C.M.S. initials, with a new place to sit. It all depends on who is sitting to your right and left.

Quick Start · Features · Documentation · Upgrading · Contributing

Why Comfy Middle Seat?

Choose Comfy Middle Seat when you want content editing inside your Rails application rather than a separate hosted CMS.

  • Keep application code and CMS-rendered pages together.
  • Own and host your content, database, and files.
  • Use familiar Rails controllers, views, helpers, authentication, and authorization.
  • Add CMS-managed pages without creating a separate frontend application.
  • Extend or override the admin area using normal Rails conventions.

Comfy Middle Seat is best suited to Rails applications that render their own websites. It is not intended to be a hosted SaaS CMS or a JavaScript-first visual page builder.

Features

For content editors

  • Hierarchical pages with fast, on-demand tree navigation.
  • Rich text, Markdown, plain text, images, files, dates, numbers, checkboxes, and reusable snippets.
  • Search across page titles, paths, and content.
  • Searchable image and file selection inside the editor.
  • Local draft recovery for Pages and Translations.
  • Revision history with comparison, preview, and restore workflows.
  • Page translations and multilingual publishing.
  • Multi-site publishing from one installation.
  • Controls to publish or unpublish child pages together.

For Rails developers

  • Drop-in Rails engine with configurable admin and public routes.
  • Flexible layouts built with simple {{ cms:... }} content tags.
  • Active Storage integration for files and images.
  • CMS seed files for version-controlled starter content.
  • Configurable authentication and authorization.
  • Extendable admin views, controllers, helpers, and partials.
  • Stable comfy_cms_* database tables for upgrades from Sofa and Surfer.
  • CI coverage across current Ruby and Rails releases.

Quick Start

Add the gem to your Rails application's Gemfile:

gem "comfy_middle_seat", "~> 4.0"

Install the gem and generate the CMS:

bundle install
bin/rails active_storage:install
bin/rails generate comfy:cms
bin/rails db:migrate
bin/rails comfy:compile_assets

The generator adds the CMS routes and creates config/initializers/comfy_middle_seat.rb.

Make sure the public content route remains after your application's other routes so it does not capture them first:

comfy_route :cms_admin, path: "/admin"
comfy_route :cms, path: "/"

Start Rails and open http://localhost:3000/admin. The generated development credentials are user and pass.

Security: Replace the default admin credentials or configure application authentication before exposing the admin area to a network.

Basic configuration

Use the ComfyMiddleSeat namespace in config/initializers/comfy_middle_seat.rb:

ComfyMiddleSeat.configure do |config|
  config.cms_title = "My CMS"
  config.admin_base_controller = "ApplicationController"
end

ComfyMiddleSeat::AccessControl::AdminAuthentication.username = "admin-user"
ComfyMiddleSeat::AccessControl::AdminAuthentication.password = "change-me"

The initializer documents additional options for authentication, authorization, revisions, locales, seeds, helpers, partials, and application integration.

How content works

A Site defines a hostname, path, and language. Layouts define page structure and the fields editors can manage. For example:

<div id="page">
  {{ cms:snippet header }}
  <div id="main">
    <div id="content">
      {{ cms:breadcrumbs }}
      {{ cms:siblings exclude: "search,comments" }}
      <hr/>
      {{ cms:markdown content }}
    </div>
  </div>
</div>

When an editor creates a Page using this Layout, the admin automatically presents fields for title and content. Content tags can also provide Markdown, files, images, dates, numbers, checkboxes, snippets, partials, helpers, navigation, and other reusable content.

Compatibility and requirements

Component Support
Ruby 3.2 or newer; CI tests 3.3, 3.4, and 4.0
Rails CI tests 7.2, 8.0, and 8.1
Node.js 18 or newer for asset compilation
File storage Active Storage
Image processing ImageMagick

Pagination is provided by Kaminari. The admin uses Bootstrap, CodeMirror, and Redactor.

Documentation

The Comfortable Media Surfer Wiki remains a reference for inherited CMS features while first-party Comfy Middle Seat documentation is expanded.

Useful starting points:

When adapting upstream examples, use the comfy_middle_seat gem, config/initializers/comfy_middle_seat.rb, and the ComfyMiddleSeat Ruby namespace.

Upgrading

From Comfortable Media Surfer

  1. Replace comfortable_media_surfer with comfy_middle_seat in the Gemfile. Do not include both gems.

  2. Run bundle install.

  3. Preview and run the standalone initializer converter from the Rails application root:

    bundle exec comfy-middle-seat-upgrade --dry-run
    bundle exec comfy-middle-seat-upgrade
  4. Replace any remaining Ruby references from ComfortableMediaSurfer to ComfyMiddleSeat.

The converter renames config/initializers/comfortable_media_surfer.rb to config/initializers/comfy_middle_seat.rb, updates namespace references, and preserves the original as a .bak file. It refuses to overwrite an existing initializer or backup.

The existing comfy_cms_* tables, schema, and stored records are used as-is. No CMS database migration is required for this upgrade.

From Comfortable Mexican Sofa

Upgrade the application to Rails 7.2 or newer, replace the old gem with comfy_middle_seat, run bundle install, generate or convert config/initializers/comfy_middle_seat.rb, and update application integrations to use ComfyMiddleSeat.

Sofa and Comfy Middle Seat use the same comfy_cms_* database table names, so the CMS tables do not need to be renamed.

From Occams

Upgrade the application to Rails 7.2 or newer and replace Occams with comfy_middle_seat. Occams used different table names and namespace values, so its data requires conversion:

ALTER TABLE occams_cms_categories RENAME TO comfy_cms_categories;
ALTER TABLE occams_cms_categorizations RENAME TO comfy_cms_categorizations;
ALTER TABLE occams_cms_files RENAME TO comfy_cms_files;
ALTER TABLE occams_cms_fragments RENAME TO comfy_cms_fragments;
ALTER TABLE occams_cms_layouts RENAME TO comfy_cms_layouts;
ALTER TABLE occams_cms_pages RENAME TO comfy_cms_pages;
ALTER TABLE occams_cms_revisions RENAME TO comfy_cms_revisions;
ALTER TABLE occams_cms_sites RENAME TO comfy_cms_sites;
ALTER TABLE occams_cms_snippets RENAME TO comfy_cms_snippets;
ALTER TABLE occams_cms_translations RENAME TO comfy_cms_translations;
UPDATE comfy_cms_categories SET categorized_type = 'Comfy::Cms::Page' WHERE categorized_type = 'Occams::Cms::Page';
UPDATE comfy_cms_categorizations SET categorized_type = 'Comfy::Cms::Page' WHERE categorized_type = 'Occams::Cms::Page';
UPDATE comfy_cms_fragments SET record_type = 'Comfy::Cms::Page' WHERE record_type = 'Occams::Cms::Page';
UPDATE comfy_cms_fragments SET record_type = 'Comfy::Cms::Layout' WHERE record_type = 'Occams::Cms::Layout';
UPDATE comfy_cms_fragments SET record_type = 'Comfy::Cms::Snippet' WHERE record_type = 'Occams::Cms::Snippet';
UPDATE comfy_cms_revisions SET record_type = 'Comfy::Cms::Page' WHERE record_type = 'Occams::Cms::Page';
UPDATE comfy_cms_revisions SET record_type = 'Comfy::Cms::Layout' WHERE record_type = 'Occams::Cms::Layout';
UPDATE comfy_cms_revisions SET record_type = 'Comfy::Cms::Snippet' WHERE record_type = 'Occams::Cms::Snippet';
UPDATE active_storage_attachments SET record_type = 'Comfy::Cms::File' WHERE record_type = 'Occams::Cms::File';

Back up the database and test this conversion outside production first.

Project history

See the Changelog, Sofa releases, and Surfer releases for the complete inherited history.

Add-ons

For blog functionality, see ComfyBlog.

Contributing

Contributions are welcome. See CONTRIBUTING.md for setup and pull-request guidance.

The main checks are:

bundle exec rake test
bundle exec rails test:system
bundle exec rubocop

Bug reports and focused feature proposals can be opened through GitHub Issues.

Acknowledgements


Copyright 2010-2019 Oleg Khabarov, 2024-2026 ShakaCode LLC, 2026 Andrew vonderLuft.

Released under the MIT License.