Iron

Iron is a flexible CMS engine for Rails apps

Usage

Publishing Content to the Web

Iron CMS allows you to publish content types to your website. To set this up:

  1. Install the pages controller in your application:
   bin/rails g iron:pages

This will:

  • Create a PagesController in your app
  • Add the iron_pages route to your routes file
  • Create a default view template
  1. Create custom templates for your content types:
   bin/rails g iron:template article

This creates a template at app/views/templates/article.html.erb that you can customize.

  1. Enable web publishing for a content type in the Iron admin panel:

    • Go to Content Types
    • Edit your content type
    • Enable "Web Published"
    • Set a base path (optional)
  2. Access your content on the web:

    • Entries will be available at their generated routes
    • Use the iron_entry_path(@entry) helper to generate URLs
    • Multi-locale support is built-in with URL prefixes

Responsive Images

Iron provides helpers for efficient, responsive image rendering with automatic variant generation and modern format support.

Setup

Include the helper in your application:

# app/helpers/application_helper.rb
module ApplicationHelper
  include Iron::ImageHelper
end

Usage

Use iron_picture_tag for optimal image delivery:

<%= iron_picture_tag field.file %>

This automatically:

  • Generates responsive variants (150w, 320w, 640w, 1024w, 1920w)
  • Serves modern formats (AVIF, WebP) with automatic fallback
  • Adds proper dimensions to prevent layout shift
  • Enables lazy loading by default
  • Displays blur placeholders during image load

Customization

Specify responsive sizes based on your layout:

<%= iron_picture_tag field.file, 
    sizes: "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw",
    class: "rounded-lg",
    loading: "eager" %>

Disable blur placeholders when not needed:

<%= iron_picture_tag field.file, blur: false %>

Alternative: Simple Image Tag

For cases where you need a basic responsive image without format optimization:

<%= iron_image_tag field.file %>

This generates a standard <img> with srcset but without modern format variants.

Development Seeding

Iron provides a seeding mechanism to snapshot and restore CMS schema and content, making it easy for teammates to get a consistent development database.

Creating a seed

After setting up your content types and sample content via the admin UI:

bin/rails iron:seed:dump

This exports the full CMS state to db/seeds/iron.zip. Commit this file to your repository.

Loading a seed

Add this to your db/seeds.rb:

Iron::Seed.load

Then rails db:prepare (or rails db:seed) will automatically bootstrap the CMS when the database is empty. Loading is skipped if content types already exist.

Admin credentials

The seed creates a default admin user during loading. Configure via environment variables:

System Requirements

Iron requires libvips to be installed on your system for image processing and responsive image generation.

macOS:

brew install vips

Ubuntu/Debian:

sudo apt-get install libvips

Arch Linux:

sudo pacman -S libvips

Note: Rails-generated production Dockerfiles typically include libvips by default, so no additional Docker configuration is needed.

Installation

Add this line to your application's Gemfile:

gem "iron-cms"

And then execute:

bundle

Or install it yourself as:

gem install iron

Then copy iron migrations:

bin/rails iron:install:migrations

Configure the mailer sender address used for system emails (e.g. password resets):

# config/environments/production.rb
config.action_mailer.default_options = { from: "[email protected]" }

Architecture

Here is an overview of how the CMS is structured.

erDiagram
    ENTRY }o--|| CONTENT_TYPE : "conforms to"
    CONTENT_TYPE ||--o{ FIELD_DEFINITION : "defines"
    CONTENT_TYPE |o--o| FIELD_DEFINITION : "title"
    BLOCK_DEFINITION |o--o{ FIELD_DEFINITION : "defines"
    FIELD_DEFINITION }o--o{ BLOCK_DEFINITION : "supports"
    ENTRY ||--o{ FIELD : "has"
    FIELD }o--|| LOCALE : "has"
    FIELD_DEFINITION ||--o{ FIELD : "defined by"
    BLOCK_DEFINITION |o--o{ FIELD : "defines"
    FIELD |o--o{ FIELD : "has"

    ENTRY {
    }
    CONTENT_TYPE {
        string name "Content type name"
        string handle "Used for the API"
        string description "Description for documentation purposes"
    }
    FIELD_DEFINITION {
        string name "Used as display name in CMS"
        string handle "Used for the API"
        string type "Definition type: text | number | file | block_definition"
        boolean localized "If the definition supports multiple locales"
    }
    BLOCK_DEFINITION {
        string name "block name"
        string handle "Used for the API"
        string description "Description for documentation purposes"
    }
    FIELD {
        string type  "Field type: text | number | block"
        string value_text "Text value (optional)"
        decimal value_number "Number value (optional)"
    }
    LOCALE {
        string code "Locale code"
        string name "Locale name"
    }

Publishing

To release a new version of the Iron gem:

  1. Update the version and changelog:

    • Update the version number in lib/iron/version.rb
    • Update CHANGELOG.md with the changes for the new version
    • Run bundle install to update the lock file with the new version
  2. Commit the changes:

   git commit -am "your commit message"
  1. Release the gem:
   bin/rails release

This command will build the gem, tag the commit with the version number, push to GitHub, and publish to RubyGems.

Contributing

Contribution directions go here.

License

The gem is available as open source under the terms of the MIT License.