Seeding Content
Lean CMS uses a YAML file to define your site’s content structure. Running a rake task converts that definition into database rows, giving editors something to work with immediately — and giving you a repeatable way to set up new environments.
The structure file
config/lean_cms_structure.yml defines every page, section, and field in your site. Pages have sections, sections have fields (and optionally cards or bullets):
site:
name: "Acme Corporation"
default_author_email: "admin@acme.com"
page_order:
- home
- about
- contact
pages:
home:
display_title: "Home"
page_order: 1
sections:
hero:
display_title: "Hero Section"
section_order: 1
fields:
heading:
type: text
label: "Hero Heading"
default: "Custom Fabrication & Machining"
subheading:
type: text
label: "Hero Subheading"
default: "Precision parts, fast turnaround."
cta_label:
type: text
label: "CTA Button Text"
default: "Request a Quote"
cta_url:
type: url
label: "CTA Button URL"
default: "/contact"
background:
type: image
label: "Background Image"
services_preview:
display_title: "Services Preview"
section_order: 2
fields:
section_heading:
type: text
label: "Section Heading"
default: "What We Do"
cards:
type: cards
max_cards: 3
items:
- icon: "gear"
icon_color: "white"
bg_color: "#2563eb"
heading: "Machining"
text: "Precision CNC machining."
alignment: "left"
about:
display_title: "About Us"
page_order: 2
sections:
intro:
display_title: "Introduction"
section_order: 1
fields:
heading:
type: text
label: "Heading"
default: "About Acme Corporation"
body:
type: rich_text
label: "About Body"
default: "<p>We've been building precision parts since 2005.</p>"
contact:
display_title: "Contact"
page_order: 3
sections:
why_partner:
display_title: "Why Partner With Us"
section_order: 1
fields:
heading:
type: text
label: "Section Heading"
default: "Why Partner With Us?"
bullets:
type: bullets
max_items: 8
items:
- "Fast turnaround"
- "No minimums"
- "USA-based"
Required keys: pages.<key>.sections.<key>.fields — fields must be nested under a fields: block (not directly on the section). This is what distinguishes regular fields from cards/bullets, which sit at the section level.
Optional keys: display_title on pages and sections (falls back to a titleized key), page_order / section_order for sorting in the CMS UI, label on fields (shown in the editor), max_length for text fields, options for dropdown fields, position for explicit field ordering.
Generate the structure
rails lean_cms:load_structure
This command:
- Reads
config/lean_cms_structure.yml - Creates
LeanCms::PageContentrecords for each field usingfind_or_create_by— safe to re-run - Sets the default content value for any newly created field
- Logs what it created
Example output:
Generating Lean CMS structure for: Acme Corporation
============================================================
Page: Home (home)
✓ hero / heading (text)
✓ hero / subheading (text)
✓ hero / cta_label (text)
✓ hero / cta_url (url)
✓ hero / background (image)
✓ services_preview / cards (cards)
Page: About Us (about)
✓ intro / heading (text)
✓ intro / body (rich_text)
============================================================
Structure generation complete!
Supported field types in YAML
type |
Description |
|---|---|
text |
Plain single-line string |
rich_text |
HTML content (Trix editor) |
image |
File upload via ActiveStorage |
boolean |
True/false toggle (default: "true" or "false") |
url |
URL string |
color |
CSS color value |
dropdown |
String from a predefined list |
cards |
JSON array of card objects |
bullets |
JSON array of bullet objects |
Exporting the current structure
If you have an existing site and want to generate a YAML file from the live database:
rails lean_cms:export_structure
This writes config/lean_cms_structure_export.yml with all existing page contents. Useful for documenting an existing install or bootstrapping a second environment.
Content migrations
For content changes after the initial seed — such as updating copy or adding a new field — use a content migration rather than re-running generate_structure:
rails generate lean_cms:content_migration update_homepage_hero
This generates a migration file pre-populated with a template:
class UpdateHomepageHero < ActiveRecord::Migration[8.0]
def up
LeanCms::PageContent.find_by(
page_id: LeanCms::Page.find_by!(slug: "home").id,
section: "hero",
key: "heading"
)&.update!(value: "New Heading Copy")
end
def down
LeanCms::PageContent.find_by(
page_id: LeanCms::Page.find_by!(slug: "home").id,
section: "hero",
key: "heading"
)&.update!(value: "Custom Fabrication & Machining")
end
end
Content migrations run automatically on deploy with rails db:migrate, so the change lands in production without any manual steps.
Multiple clients
If you manage multiple client sites, keep a separate structure file per client:
config/
lean_cms_structure_acme.yml
lean_cms_structure_widgets_co.yml
Load a specific file:
rails lean_cms:load_structure[config/lean_cms_structure_acme.yml]