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_initialize_by— safe to re-run - Sets the default content value for any newly created field
- Logs what it created
Example output:
Loading LeanCMS page content structure...
Using system user: admin@acme.com
============================================================
Page: HOME (Home) [order: 1]
Section: hero (Hero Section) [order: 1]
✓ Created: heading (text)
✓ Created: subheading (text)
✓ Created: cta_label (text)
✓ Created: cta_url (url)
✓ Created: background (image)
Section: services_preview (Services Preview) [order: 2]
✓ Created: section_heading (text)
✓ Created: cards (3 items)
Page: ABOUT (About Us) [order: 2]
Section: intro (Introduction) [order: 1]
✓ Created: heading (text)
✓ Created: body (rich_text)
============================================================
Summary:
Total fields: 9
Created: 9
Updated: 0
Skipped: 0
============================================================
On re-runs, unchanged fields show as - Skipped, and changed metadata (label, position, options) shows as ↻ Updated. The stored content value is only set on Created — re-runs do not overwrite editor changes.
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 every page, section, and field — using each field’s current value as its default. Useful for bootstrapping a second environment from production data, or for documenting an existing install. Override the output path with OUTPUT=:
rails lean_cms:export_structure OUTPUT=config/lean_cms_structure_staging.yml
Image attachments are not included in the export — re-attach via the CMS UI or copy ActiveStorage blobs separately.
Updating content after the initial seed
For copy edits and tweaks, just edit through /lean-cms — that’s the whole point of the CMS. For structural changes (new field, renamed section), edit config/lean_cms_structure.yml and re-run lean_cms:load_structure — it’s idempotent and won’t clobber editor changes to existing fields. For one-off data updates across environments, use the content sync workflow (lean_cms:sync:pull / lean_cms:sync:push).
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]