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:
- Install the pages controller in your application:
bin/rails g iron:pages
This will:
- Create a
PagesControllerin your app - Add the
iron_pagesroute to your routes file - Create a default view template
- 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.
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)
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:
IRON_SEED_EMAIL(default:[email protected])IRON_SEED_PASSWORD(default:password)
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. = { 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:
Update the version and changelog:
- Update the version number in
lib/iron/version.rb - Update
CHANGELOG.mdwith the changes for the new version - Run
bundle installto update the lock file with the new version
- Update the version number in
Commit the changes:
git commit -am "your commit message"
- 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.