%= lato_page_head "Documentation" %>
lato_cms adds content management to a Lato admin panel.
Use it when admins need to create pages and edit structured content without changing application code.
Lato CMS works with Lato Spaces, so pages can be scoped to the selected group.
Add Lato CMS to the application Gemfile:
gem "lato"
gem "lato_spaces"
gem "lato_cms"
Install the engine and run migrations:
bundle
rails lato_cms:install:application
rails lato_cms:install:migrations
rails db:migrate
Mount the engine in config/routes.rb:
Rails.application.routes.draw do
mount LatoCms::Engine => "/lato-cms"
# ...
end
Import styles in app/assets/stylesheets/application.scss:
@import "lato_cms/application";
Import JavaScript in app/javascript/application.js:
import "lato_cms/application"
Users must be logged into Lato, must have a selected Lato Spaces group, and must have Lato CMS admin permission enabled.
user = Lato::User.find_by(email: "admin@example.com")
user.update!(lato_cms_admin: true)
Configure available locales and template directory:
LatoCms.configure do |config|
config.locales = [:en, :it]
config.templates_path = "config/lato_cms"
end
Templates define which content blocks are available on a page. Components define the fields inside those blocks. Both are YAML files stored in the application. Template components are enabled by default, and each page can turn optional components on or off from the admin panel.
config/lato_cms/
templates/
homepage.yml
blog_post.yml
components/
hero.yml
content.yml
Generate new files with Rails tasks:
rails "lato_cms:generate:template[blog_post]"
rails "lato_cms:generate:component[hero,title:string,subtitle:textarea,image:file]"
# config/lato_cms/templates/homepage.yml
id: homepage
name: Homepage
components:
hero_section:
component_id: hero
name: Hero Section
required: true
content_section:
component_id: content
Components listed in a template are optional unless required: true is set.
Optional components show an enabled switch in the page editor. Admins can disable them for a specific page
without removing the component from the template.
# config/lato_cms/templates/homepage.yml
id: homepage
name: Homepage
components:
hero_section:
component_id: hero
name: Hero Section
required: true
banner_section:
component_id: banner
name: Promotional Banner
content_section:
component_id: content
name: Content
In this example hero_section is always active and cannot be disabled.
banner_section and content_section can be enabled or disabled per page.
Disabled components are hidden in the editor, cannot be saved, and are not exposed when page fields are returned by the API.
Add repeater: true to a template component when admins need to create multiple items with the same field set.
The API returns repeater fields as an ordered array of items.
# config/lato_cms/templates/homepage.yml
components:
feature_cards:
component_id: feature_card
name: Feature Cards
repeater: true
settings:
min: 1
# config/lato_cms/components/feature_card.yml
id: feature_card
name: Feature Card
fields:
title:
name: Title
type: string
required: true
description:
name: Description
type: textarea
# config/lato_cms/components/hero.yml
id: hero
name: Hero
fields:
title:
name: Title
type: string
required: true
subtitle:
name: Subtitle
type: textarea
image:
name: Image
type: file
settings:
accept: "image/*"
attachments:
name: Attachments
type: file
settings:
multiple: true
| Type | Use for |
|---|---|
string |
Short text. |
textarea |
Multi-line plain text. |
text |
Long rich text or HTML content. |
number |
Numeric values. |
date / datetime |
Date and time values. |
boolean |
True/false values. |
select / multiselect |
One or more values from predefined options. |
color |
Color values. |
json |
Structured data. |
file |
Single file upload through Active Storage by default. Set settings.multiple: true to allow multiple files. |
image |
Single image upload through Active Storage. |
gallery |
Multiple sortable image uploads through Active Storage. |
custom |
Application-defined field rendered with a custom partial. |
Use type: custom when a component needs an editor that is not covered by built-in field types.
Set render to an application partial path. The partial receives field_id,
field_config, and page_field locals.
# config/lato_cms/components/hero.yml
id: hero
name: Hero
fields:
icon_note:
name: Icon note
type: custom
render: lato_cms/custom_fields/icon_note
required: false
settings:
placeholder: "Example: rocket|Hero launch section"
Create the partial in the host application:
<%# app/views/lato_cms/custom_fields/_icon_note.html.erb %>
<% settings = field_config["settings"] || {} %>
<% current_value = page_field&.value.to_s %>
<label class="form-label" for="fields_<%= field_id %>_value">
<%= field_config["name"] || field_id.humanize %>
</label>
<input type="text"
class="form-control"
name="fields[<%= field_id %>][value]"
id="fields_<%= field_id %>_value"
value="<%= current_value %>"
placeholder="<%= settings["placeholder"] %>">
Custom field values are saved like standard scalar fields when the input name is
fields[FIELD_ID][value]. Use settings for custom options consumed by the partial.
Use Lato CMS pages as structured content records for public or private pages. Field values are available in their parsed form, so numbers, booleans, dates, JSON values, multi-select values, and files can be consumed directly by application views or serializers.
page = LatoCms::Page.find_by(permalink: "/homepage")
title = page.fields.find_by(field_id: "title")&.parsed_value
image = page.fields.find_by(field_id: "image")&.files&.first