Skip to content

Rendering Images ​

Images are stored as originals in the Alchemy picture library. Editors assign these images to Picture ingredients on elements. You control the rendering dimensions, cropping, and output format through ingredient settings and rendering options.

Alchemy supports two storage adapters: ActiveStorage and Dragonfly. Both use the same rendering API, so you can switch between them without changing your templates.

Configuration ​

Image rendering is configured in your initializer. See the Configuration guide for all available options.

ruby
# config/initializers/alchemy.rb
Alchemy.configure do |config|
  config.output_image_quality = 85
  config.preprocess_image_resize = "1000x1000"
  config.image_output_format = "original"
  config.sharpen_images = false
end

TIP

You can override the output format and quality per ingredient by passing format and quality as rendering options.

Rendering ​

In most cases, rendering a Picture ingredient through el.render(:image) in your element view is all you need. It generates the correct image URL with all configured options applied.

erb
<%# app/views/alchemy/elements/_article.html.erb %>
<%= el.render(:hero_image) %>

The output depends on what the editor has configured on the picture:

  • Image only — renders an <img> tag
  • With caption — wraps in a <figure> with a <figcaption>
  • With link — wraps the image in an <a> tag
  • With caption and link — wraps the linked image in a <figure> with a <figcaption>

Ingredient Settings ​

Configure rendering in your elements.yml definition.

yaml
- name: article
  ingredients:
    - role: hero_image
      type: Picture
      settings:
        size: 1200x600
        crop: true

See the Picture ingredient settings for the full list of options.

Rendering Options ​

These options control how the image variant is generated.

size ​

String

The dimensions to resize the image to, preserving aspect ratio. Example: "400x300".

crop ​

Boolean

Crop the image to exactly match the given size.

format ​

String

The output format: "jpg", "png", "gif", or "webp".

quality ​

Integer

The quality of rendered JPEG and WebP images.

upsample ​

Boolean

Allow the image to be scaled up beyond its original dimensions. By default, images are only scaled down.

Responsive Images ​

Use the srcset and sizes ingredient settings to generate responsive <img> tags with multiple sources.

yaml
- role: photo
  type: Picture
  settings:
    size: 1200x800
    crop: true
    srcset: ['400x267', '800x533', '1200x800']
    sizes: ['(max-width: 600px) 400px', '(max-width: 900px) 800px', '1200px']

This renders an <img> tag with a srcset attribute containing URLs for each size and a sizes attribute telling the browser which source to use at each viewport width.

Formats 8.4+ ​

Since Alchemy 8.4, the format setting converts the image into another format, and srcset entries can be a hash with a size and their own format.

yaml
- role: photo
  type: Picture
  settings:
    format: webp
    srcset:
      - 400x267
      - size: 800x533
        format: png
      - size: 1200x800
        format: webp

The main image and the 400x267 entry are rendered as WebP because of the format setting, the 800x533 entry as PNG. A format is only applied if the picture can be converted, so SVG files are rendered as they are.

All entries end up in the srcset of a single <img> tag, where the browser chooses by width only. Entries with the same size in different formats do not act as fallbacks for each other. To offer a format with a fallback, render a <picture> element with one <source> per format yourself, using ingredient.picture_srcset_options, which returns the url, desc, width, height and mime type of each entry.

TIP

New formats create new image variants. Generate them upfront instead of on the first request with:

bash
bin/rake alchemy:generate:ingredient_picture_thumbnails

Set ELEMENTS=element1,element2 to only generate thumbnails for some elements and ASYNC=true to enqueue them as background jobs (ActiveStorage only).

Remote Storage ​

In production you typically want to store images on a remote service like Amazon S3, Google Cloud Storage, or Azure Storage instead of the local filesystem.

With ActiveStorage, configure your storage service in config/storage.yml and set the active service in your environment config, just like any Rails application. See the Active Storage Overview in the Rails guides.

yaml
# config/storage.yml
amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: eu-central-1
  bucket: my-app-production
ruby
# config/environments/production.rb
config.active_storage.service = :amazon

With Dragonfly, use the alchemy-dragonfly-s3 extension to store images on S3 compatible services.

TIP

See Extensions for all available storage add-ons.

Caching ​

Alchemy caches rendered image variants automatically. The caching strategy depends on your storage adapter.

ActiveStorage uses Rails' built-in variant caching. Variants are generated on first request and stored alongside the original blob.

Dragonfly uses Alchemy's PictureThumb model to cache rendered variants in the database. Three admin thumbnail sizes are pregenerated on upload.

In both cases, adding a CDN in front of your application is recommended for production to avoid hitting the application server for repeated image requests.

BSD-3 Licensed · Hosting sponsored by netlify