Skip to content

WNCMS Theme Config Specification

This document defines the complete structure and usage of config.php inside every WNCMS theme.

A theme config contains:

  1. Theme metadata (info)
  2. Theme option groups (option_tabs)
  3. Default values (default)

1. info — Theme Metadata

Structure

KeyTypeRequiredDescription
labelstringyesTheme display name
namestringyesTheme ID, same as folder name
authorstringyesCreator name
descriptionstringyesBrief description
versionstringyesSemantic version (e.g. 1.0.0)
created_atstringyesYYYY-MM-DD
updated_atstringyesLast update date

Example

php
'info' => [
    'label'       => 'WNCMS Starter Theme',
    'name'        => 'starter',
    'author'      => 'Winnie',
    'description' => 'Official WNCMS base theme',
    'version'     => '1.0.0',
    'created_at'  => '2025-01-01',
    'updated_at'  => '2025-12-01',
],

2. option_tabs — Option Groups

option_tabs is a multi-tab layout where each tab holds many input options.

Example:

php
'option_tabs' => [
    'general' => [
        [
            'label' => 'General Settings',
            'type'  => 'heading',
        ],
        [
            'label' => 'Subtitle',
            'name'  => 'subtitle',
            'type'  => 'text',
        ],
    ],
],

Field Types Reference

Each field type supports different keys. Below are all supported types with tables and examples.

Basic Text & Number

text

KeyTypeRequiredExample
labelstringyes"Site Name"
namestringyes"site_name"
typestringyes"text"
defaultstringno"My Website"
descriptionstringno"Shown in header"

Example:

php
[
    'label' => 'Site Name',
    'name'  => 'site_name',
    'type'  => 'text',
],

Type Switching Compatibility (Array -> Text / Textarea)

When a template option is changed from an array-like type (for example gallery, accordion) to text or textarea:

  • Old saved JSON array/object values are kept as raw JSON strings in the edit form.
  • The page edit form no longer force-decodes those JSON strings for scalar fields.
  • Saving the page after editing the field stores the value as plain text.

Example conversion expectation:

  • Old type: gallery
  • Old stored value: [{"image":"/uploads/a.jpg","text":"A","url":""}]
  • New type: text
  • Edit form value shown: [{"image":"/uploads/a.jpg","text":"A","url":""}] (string)
  • After save (if edited to Homepage hero): stored value becomes Homepage hero

number

KeyTypeRequiredExample
labelstringyes"Items per page"
namestringyes"per_page"
typestringyes"number"
defaultintno12

Example:

php
[
    'label' => 'Items per page',
    'name'  => 'per_page',
    'type'  => 'number',
],

Media / Image

image

KeyTypeRequiredExample
labelstringyes"Top Banner"
namestringyes"banner"
typestringyes"image"
widthint/stringno800 / "50%" / "auto"
heightint/stringno300 / "auto"
aspect_ratiostringno"16/9"

Behavior:

  • If width only → height auto-calculated via aspect ratio
  • If height only → width auto-calculated
  • If both missing → defaults to width 400px, height auto

Example:

php
[
    'label' => 'Homepage Banner',
    'name'  => 'home_banner',
    'type'  => 'image',
    'width' => 800,
    'aspect_ratio' => '16/9',
],

display_image (Static Preview Image)

KeyTypeRequiredExample
labelstringyes"Preview"
typestringyes"display_image"
pathstringyes"theme/starter/images/demo.png"
widthint/stringno300 / "100%"
heightint/stringno120
aspect_ratiostringno"4/3"
colstringno"col-12 col-md-4"

Behavior:

  • Does not store data
  • Used only for admin preview images
  • If width/height missing → width=100%, height=auto
  • col supports Bootstrap grid

Example:

php
[
    'label' => 'Ad Slot Preview',
    'type'  => 'display_image',
    'path'  => 'starter/images/hero-demo.png',
    'col'   => 'col-12 col-md-4',
],

Gallery (Multiple Images)

KeyTypeRequiredExample
labelstringyes"Gallery"
namestringyes"hero_gallery"
typestringyes"gallery"
desktop_columnsintno4
mobile_columnsintno2
widthint/stringno300 / "50%"
heightint/stringno"auto"
aspect_ratiostringno"1/1"

Stored Value Example:

json
[
  { "image": "/uploads/a.jpg", "text": "", "url": "" },
  { "image": "/uploads/b.jpg", "text": "", "url": "" }
]

Example Config:

php
[
    'label' => 'Homepage Gallery',
    'name'  => 'hero_gallery',
    'type'  => 'gallery',
    'desktop_columns' => 4,
    'mobile_columns'  => 2,
    'aspect_ratio'    => '1/1',
],

Select / Boolean

select

KeyTypeRequiredExample
labelstringyes"Category"
namestringyes"category"
typestringyes"select"
optionsarray/stringyes["A","B"] or "posts" or "menus"
tag_typestringno"post_category"

Example:

php
[
    'label'   => 'Category',
    'name'    => 'category',
    'type'    => 'select',
    'options' => 'posts',
],

boolean

KeyTypeRequiredExample
labelstringyes"Show Banner?"
namestringyes"show_banner"
typestringyes"boolean"
defaultintno1

Textarea

textarea

KeyTypeRequiredExample
labelstringyes"About"
namestringyes"about"
typestringyes"textarea"
defaultstringno""

Color

color

KeyTypeRequiredExample
labelstringyes"Brand"
namestringyes"brand"
typestringyes"color"
requiredboolnotrue
placeholderstringno"#FFA218"
defaultstringno"#FFA218"

Behavior:

  • Color input now supports required and placeholder.
  • Default display value is #FFA218 when empty.

Repeater

repeater

KeyTypeRequiredExample
labelstringyes"Slides"
namestringyes"hero_slides"
typestringyes"repeater"
fieldsarrayyesfield schema
add_labelstringno"Add Slide"

Behavior:

  • Repeater JS is loaded from local wncms/js/jquery.repeater.min.js (not CDN).
  • Starter repeater rows use overflow-safe layout (overflow-auto) to avoid horizontal clipping.

fields supports simple input configs:

php
[
    'label' => 'Hero Slides',
    'name' => 'hero_slides',
    'type' => 'repeater',
    'fields' => [
        ['name' => 'text', 'type' => 'text', 'label' => 'Text'],
        ['name' => 'number', 'type' => 'number', 'label' => 'Number'],
    ],
]

Editor (TinyMCE)

editor

KeyTypeRequiredExample
labelstringyes"Content"
namestringyes"content"
typestringyes"editor"

Structure Layout

heading

KeyTypeRequiredExample
labelstringyes"General Settings"
typestringyes"heading"
descriptionstringno"Section description"

sub_heading

KeyTypeRequiredExample
labelstringyes"Homepage Banner"
typestringyes"sub_heading"

inline

KeyTypeRequiredExample
labelstringyes"Three Columns"
namestringyes"stats"
typestringyes"inline"
sub_itemsarrayyesmultiple inputs
repeatintno3

accordion

KeyTypeRequiredExample
labelstringyes"FAQ"
namestringyes"faq_items"
typestringyes"accordion"
contentarrayyesfields inside FAQ
sortableboolnotrue
repeatintno3

Hidden

hidden

KeyTypeRequiredExample
labelstringno""
namestringyes"token"
typestringyes"hidden"
defaultstringyes"123"

3. default — Default Values

Example:

php
'default' => [
    'site_name' => 'My Website',
    'subtitle'  => 'Just another WNCMS site',
    'show_banner' => 1,
],

4. pages — Theme Pages Configuration

The pages array defines custom theme pages that can be added to menus through the WNCMS backend menu editor.

Structure

php
'pages' => [
    'page_key' => [
        'label' => 'Display label',
        'key'   => 'translation_key',
        'route' => 'route.name',
        'blade' => 'path.to.blade',
    ],
],

Keys

KeyTypeRequiredDescription
labelstringyesDisplay label shown in menu editor (not translated)
keystringyesTranslation key used for localization (theme::word.key)
routestringyesLaravel route name (must be registered in routes/web.php)
bladestringyesBlade file path relative to theme views directory

Example

php
'pages' => [
    'blog' => [
        'label' => '部落格頁面',
        'key'   => 'blog',
        'route' => 'frontend.pages.blog',
        'blade' => 'pages.blog',
    ],
    'about' => [
        'label' => '關於我們',
        'key'   => 'about',
        'route' => 'frontend.pages.about',
        'blade' => 'pages.about',
    ],
],

Usage

  1. Define the page configuration in your theme's config.php
  2. Create the corresponding blade file in themes/yourtheme/views/pages/blog.blade.php
  3. Register the route in your theme or application routes
  4. The page will appear in the backend menu editor under "Theme Pages"
  5. Admins can add the page to any menu by selecting it from the theme pages list

Translation

The label field is displayed as-is in the menu editor. For multi-language support, create translation keys:

php
// resources/themes/yourtheme/lang/en/word.php
return [
    'blog' => 'Blog',
];

// resources/themes/yourtheme/lang/zh_TW/word.php
return [
    'blog' => '部落格',
];

Built with ❤️ for WNCMS