Configuration Files Reference

Unfold CMS templates use JSON configuration files to declare metadata, settings UI, page allow-lists, and section schemas. This page documents the complete schema for each file.

template.json

Required. Defines the template's identity, menu locations, and ad zones. Located at the template root directory.

Example

{
    "name": "Default Template",
    "version": "1.0.0",
    "author": "Unfold CMS",
    "description": "The default template for Unfold CMS",
    "screenshot": "screenshot.png",
    "menu_locations": {
        "header": {
            "name": "Header Navigation",
            "description": "Main navigation shown in the site header"
        },
        "footer": {
            "name": "Footer Navigation",
            "description": "Footer columns — top-level items become column headers, children become links"
        }
    },
    "zones": {
        "header_leaderboard": {
            "name": "Header Leaderboard",
            "description": "Top of the page leaderboard banner",
            "size": "728x90",
            "type": "banner"
        },
        "sidebar_top": {
            "name": "Sidebar Top",
            "size": "300x250",
            "type": "sidebar"
        }
    }
}

Fields

Field Type Required Description
name string Yes Human-readable template name
version string No Semantic version string
author string No Template author name
description string No Short description
screenshot string No Preview image filename (relative to template root)
menu_locations object No Menu slots the template supports. Falls back to default header and footer if omitted.
zones object Yes Ad zone definitions. Use {} if no ad zones are needed.
Field Type Description
name string Display name in admin
description string Help text for admins

Zone Object

Field Type Description
name string Display name in admin
description string Help text
size string Dimensions (e.g., 728x90, 300x250)
type string Zone type: banner, sidebar, popup, footer

options.json

Optional. Defines the template settings UI rendered in Admin > Appearance > Template Settings. Located at config/options.json within the template directory.

Example

{
    "options": [
        {
            "type": "divider",
            "label": "Homepage"
        },
        {
            "key": "hero.enabled",
            "type": "boolean",
            "label": "Show Hero Section",
            "description": "Display the hero banner on the homepage",
            "defaultValue": true,
            "col": 2,
            "children": [
                {
                    "key": "hero.title",
                    "type": "text",
                    "label": "Hero Title",
                    "defaultValue": "Welcome to Our Blog"
                },
                {
                    "key": "hero.subtitle",
                    "type": "textarea",
                    "label": "Hero Subtitle",
                    "defaultValue": "Discover stories and expertise.",
                    "rows": 3
                }
            ]
        },
        {
            "key": "blog.posts_per_page",
            "type": "integer",
            "label": "Posts Per Page",
            "defaultValue": 12,
            "min": 4,
            "max": 48
        },
        {
            "key": "appearance.default_theme",
            "type": "radio",
            "label": "Default Theme",
            "options": [
                { "value": "system", "label": "System" },
                { "value": "light", "label": "Light" },
                { "value": "dark", "label": "Dark" }
            ],
            "defaultValue": "system",
            "col": 2
        }
    ]
}

Field Types

Type Description Extra Properties
text Single-line text input placeholder
textarea Multi-line text input placeholder, rows
integer Number input min, max
boolean Toggle switch children, bordered
select Dropdown options: [{value, label}]
radio Radio button group options: [{value, label, description}], inline
color Color picker
url URL input placeholder
file File upload file: {accept, maxSize, preview}
slider Range slider slider: {min, max, step, unit}
divider Section heading (no key) label, action: {label, href}

Common Properties

Property Type Description
key string Setting key (stored as template.{name}.{key})
type string Field type (see table above)
label string Display label
description string Help text shown below the field
defaultValue mixed Default value
col number Columns to span (1 or 2)
bordered boolean Show border around field (default: true)

Boolean Children

Boolean fields can have children — nested fields that appear when the toggle is enabled:

{
    "key": "sidebar.enabled",
    "type": "boolean",
    "label": "Show Sidebar",
    "defaultValue": true,
    "children": [
        {
            "key": "sidebar.position",
            "type": "radio",
            "label": "Position",
            "options": [
                { "value": "left", "label": "Left" },
                { "value": "right", "label": "Right" }
            ],
            "defaultValue": "right"
        }
    ]
}

Reading Options in Templates

{{-- Escaped output --}}
@option('hero.title')

{{-- With default --}}
@templateOption('blog.posts_per_page', 12)

{{-- In PHP logic --}}
@php
    $postsPerPage = template_option('blog.posts_per_page', 12);
@endphp

pages.json

Optional. Declares which pages the template exposes in the page builder, and which section types each page allows. Located at config/pages.json within the template directory.

Example

{
    "homepage": {
        "label": "Homepage",
        "description": "Sections displayed on your site's homepage",
        "url": "/",
        "allow": ["hero", "logos", "stats", "features", "testimonials", "faq", "cta"]
    },
    "contact": {
        "label": "Contact Page",
        "description": "Sections displayed on the contact page",
        "url": "/contact",
        "allow": ["contact_info", "contact_form", "contact_faq", "contact_map"]
    },
    "site": {
        "label": "Site-wide",
        "description": "Sections shown on every page.",
        "url": null,
        "allow": ["header", "footer"]
    }
}

Page Properties

Field Type Required Description
label string Yes Human-readable page name shown in admin
description string No Help text in the page builder
url string|null Yes Page URL for the preview link; null for site-wide pages
allow array Yes Section type IDs (folder names) permitted on this page

sections/{id}/section.json

Required for each section type. Defines the schema for one section type. Located inside the section folder: sections/{id}/section.json.

Example

{
    "name": "Features",
    "description": "Feature cards grid with icons and optional links",
    "block_type": "features",
    "icon": "Zap",
    "max": 3,
    "reusable": true,
    "settings_only": false,
    "supports_featured_image": false,
    "version": 1,
    "fields": [
        { "key": "icon", "type": "icon_picker", "label": "Icon", "placeholder": "Search icons..." },
        { "key": "link_url", "type": "url", "label": "Link URL" }
    ],
    "settings": [
        { "key": "badge", "type": "text", "label": "Badge" },
        { "key": "title", "type": "text", "label": "Title", "col": 2 },
        { "key": "subtitle", "type": "text", "label": "Subtitle", "col": 2 }
    ]
}

Properties

Field Type Required Description
name string Yes Display name in admin
description string No Help text for admins
block_type string Yes Internal type identifier (should match the folder name)
icon string No Lucide icon name for the admin section card
max integer No Maximum placements of this type per page
reusable boolean No Whether the same type can be placed more than once
settings_only boolean No No items — settings form only
supports_featured_image boolean No Allow image upload per item
version integer No Schema version (increment when breaking changes are made)
fields array No Per-item custom fields
settings array No Section-level settings

Field / Setting Properties

Property Type Description
key string Field identifier
type string Input type (see table below)
label string Display label
description string Help text below the field
placeholder string Input placeholder
defaultValue mixed Default value
col number Columns to span (1 or 2)
options array For select type: [{value, label}]
validation object Validation rules (e.g., {required: true})
children array Nested fields shown when a boolean toggle is on
file object For file type: {accept, maxSize, preview}
slider object For slider type: {min, max, step, unit}
rows integer For textarea type: number of rows

Field Types

Type Description
text Single-line text input
textarea Multi-line text input
url URL input with validation
email Email input
integer Number input
boolean Toggle switch (supports children)
select Dropdown with options
radio Radio buttons with options
color Color picker
file File / image upload
slider Range slider
icon_picker Lucide icon search and select

Boolean Children

Boolean fields can contain nested children that appear when the toggle is on:

{
    "key": "button_primary",
    "type": "boolean",
    "label": "Primary Button",
    "defaultValue": true,
    "children": [
        { "key": "button_primary_label", "type": "text", "label": "Label", "defaultValue": "Get started" },
        { "key": "button_primary_url", "type": "url", "label": "Link", "defaultValue": "/register" }
    ]
}

Children are stored as flat keys alongside their parent — not nested objects.

File Locations

File Path Purpose
template.json resources/views/templates/{name}/template.json Template identity
options.json resources/views/templates/{name}/config/options.json Admin settings UI
pages.json resources/views/templates/{name}/config/pages.json Page definitions + section allow-lists
section.json resources/views/templates/{name}/sections/{id}/section.json Section type schema
seed.json resources/views/templates/{name}/sections/{id}/seed.json Demo content for installer