Alchemy cms

Core concept

Elements

An Element is a reusable content block you place on a Page. Each Element is defined in elements.yml and made of typed Ingredients.

config/alchemy/elements.yml
- name: concept_intro
  hint: true
  ingredients:
    - role: eyebrow
      type: Text
      hint: true
      default: :concept_intro_eyebrow
    - role: headline
      type: Headline
      as_element_title: true
      hint: true
      default: :concept_intro_headline
      settings:
        levels: [1, 2]
        sizes: [1, 2]
        anchor: from_value
    - role: lead
      type: Richtext
      hint: true
      default: :concept_intro_lead
      settings:
        tinymce:
          toolbar: "bold italic | alchemy_link unlink"
        sanitizer:
          tags: [p, br, strong, em, a]
          attributes: [href, target, rel, title]

Composing a page from Elements

A Page Layout lists which Elements a page may contain. Editors then:

  • add and remove Elements,
  • sort and nest them,
  • fill in their Ingredients.

The frontend renders each Element with its own view partial.

config/alchemy/elements.yml
- name: prose
  hint: true
  ingredients:
    - role: headline
      type: Headline
      hint: true
      default: :prose_headline
      settings:
        levels: [2, 3]
        sizes: [2, 3]
    - role: text
      type: Richtext
      hint: true
      default: :prose_text
      settings:
        tinymce:
          toolbar: "bold italic | bullist numlist | alchemy_link unlink"
        sanitizer:
          tags: [p, br, strong, em, a, ul, ol, li]
          attributes: [href, target, rel, title]
Photo-03

Every Element has a view

Elements render through a partial in app/views/alchemy/elements, so their markup is entirely under your control.

config/alchemy/elements.yml
- name: image_text
  hint: true
  ingredients:
    - role: image
      type: Picture
      hint: true
      settings:
        size: 640x480
        srcset: [320x240, 640x480]
        sizes: ["(min-width: 768px) 50vw", "100vw"]
    - role: headline
      type: Headline
      as_element_title: true
      hint: true
      default: :image_text_headline
      settings:
        levels: [2, 3]
        sizes: [2, 3]
        anchor: how
    - role: text
      type: Richtext
      hint: true
      default: :image_text_text
      settings:
        tinymce:
          toolbar: "bold italic | alchemy_link unlink"
        sanitizer:
          tags: [p, br, strong, em, a]
          attributes: [href, target, rel, title]
    - role: layout
      type: Select
      group: styling
      hint: true
      default: "md:flex-row"
      settings:
        select_values:
          - ["Image left", "md:flex-row"]
          - ["Image right", "md:flex-row-reverse"]

Tip: open โ€œHow this block is builtโ€ wherever you see it to get that blockโ€™s exact definition and jump straight to it in the admin.

config/alchemy/elements.yml
- name: callout
  hint: true
  ingredients:
    - role: variant
      type: Select
      group: styling
      hint: true
      default: info
      settings:
        select_values:
          - ["Info", "info"]
          - ["Tip", "tip"]
          - ["Warning", "warning"]
    - role: text
      type: Richtext
      hint: true
      default: :callout_text
      settings:
        tinymce:
          toolbar: "bold italic | alchemy_link unlink"
        sanitizer:
          tags: [p, br, strong, em, a]
          attributes: [href, target, rel, title]
Concept-schedule

Scheduled elements

Every Element can be given its own start and end date, so content appears and disappears on schedule โ€” a launch banner, a seasonal promo. This very note is scheduled (visible 2026โ€“2030); after its end date it would simply drop off the page.

config/alchemy/elements.yml
- name: scheduled_note
  hint: true
  ingredients:
    - role: headline
      type: Headline
      hint: true
      settings:
        levels: [2, 3]
        sizes: [3, 4]
    - role: text
      type: Richtext
      hint: true
      settings:
        tinymce:
          toolbar: "bold italic | alchemy_link unlink"
        sanitizer:
          tags: [p, br, strong, em, a]
          attributes: [href, target, rel, title]
    - role: illustration
      type: Picture
      hint: true

config/alchemy/elements.yml

- name: prose
  ingredients:
    - role: headline
      type: Headline
    - role: text
      type: Richtext

config/alchemy/elements.yml
- name: code_sample
  hint: true
  ingredients:
    - role: caption
      type: Text
      hint: true
      default: :code_sample_caption
    - role: language
      type: Select
      hint: true
      default: yaml
      settings:
        select_values:
          - ["YAML", "yaml"]
          - ["Ruby", "ruby"]
          - ["ERB", "erb"]
          - ["HTML", "html"]
    - role: code
      type: Html
      hint: true
      default: :code_sample_code