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:

  1. Reads config/lean_cms_structure.yml
  2. Creates LeanCms::PageContent records for each field using find_or_create_by — safe to re-run
  3. Sets the default content value for any newly created field
  4. 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]