LeafCMS GitHub Install
Docs

The in-app guide

This is the same guide as Admin → Help: usage, each admin screen, themes, tags, environment, and install.

The front only uses @cms*. Loop tags need a matching end tag. The loop variable is $item; nested loops must set 'as' => 'alias'. Skins: Themes. Files: Templates.

Typical examples

@cmsChannel(['type' => 'top', 'ismenu' => 1])
    <a href="{{ $item->frontUrl() }}">{{ $item->t('title') }}</a>
@endcmsChannel

@cmsContent(['model' => 'article', 'num' => 6])
    <a href="{{ $item->url }}">{{ $item->t('title') }}</a>
@endcmsContent

@cmsAdv(['name' => 'home_banner'])
    <img src="{{ cms_media($item->image) }}" alt="{{ $item->t('title') }}">
@endcmsAdv

Section list

@cmsContent(['page' => true, 'num' => $category->page_size ?: 10])
    <article>
        <div>@cmsDate(['name' => $item->published_at])</div>
        <h3><a href="{{ $item->url }}">{{ $item->t('title') }}</a></h3>
        <p>@cmsSubstr(['name' => $item->t('excerpt') ?: $item->t('content'), 'len' => 100])</p>
    </article>
@endcmsContent
@cmsPaginate

Show page

@cmsBreadcrumb
<h1>{{ $entry->t('title') }}</h1>
<div>{!! $entry->linked_content ?? $entry->t('content') !!}</div>
<p>Previous: @cmsPrev Next: @cmsNext</p>

Nested loops (rename required)

@cmsChannel(['type' => 'top', 'as' => 'cat'])
    <h2>{{ $cat->t('title') }}</h2>
    @cmsContent(['catid' => $cat->id, 'num' => 4, 'as' => 'row'])
        <a href="{{ $row->url }}">{{ $row->t('title') }}</a>
    @endcmsContent
@endcmsChannel

Directive list

DirectiveRoleCommon args
@cmsSeotitle / keywords / descriptionNo args; put in <head>
@cmsChannelSection looptype=top|son|peer|selftop, ismenu, num, name (id or slug)
@cmsMenuAdmin menu; falls back to sectionslocation=header (default)
@cmsContentEntry listcatid, model, flag, num, page, order, insub, related + related_field
@cmsPaginatePager (with page=>true)Optional view name
@cmsArconeOne entryaid or id
@cmsAdvBlockname required; num; images via cms_media($item->image); HTML items in $item->html. Friend links use partners or friend_links
@cmsBreadcrumbBreadcrumbsymbol, class
@cmsPrev / @cmsNextPrev/next in the same sectionfield, msg
@cmsDateFormat a datename or value, format=Y-m-d
@cmsSubstrPlain-text clipname, len=80, dot
@cmsFilterModel filtersmodel; query ?filter[field]=value
@cmsOrderSort links$item->url / label / current
@cmsFileinfoAttachment infofield or name, aid
@cmsFormFull form (captcha included)slug, captcha, submit
@cmsFormFieldsField loop onlyslug
@cmsTaglistTag cloudnum=20
@cmsMapOpenStreetMap embedpoint=lng,lat, address, width, height

More on @cmsContent

With no catid, a list page uses the current section (including children; insub=>false turns that off). catid=>0 or 'all' means any section. model can be a slug (article) or id. flag filters flags. related finds related docs, e.g. manga chapters: related=>$entry->id, related_field=>'manga_id'.

Helpers

FunctionRole
cms_media($path)Asset URL. Honors the CDN in Settings; with CMS_MEDIA_DISK=s3 it points at object storage
cms_route('download', $entry)Named route with locale prefix
cms_front_url('news')Front path
cms_ui('search')Theme phrase. Site-wide defaults live in Languages → Theme phrases; a skin can override them on its Configure page. cms_ui('hello', ['name' => $name]) replaces :name.
cms_theme('home_notice')Per-theme options from Configure. Keys come from theme.json config, plus defaults such as the home notice and CTA.
cms_t('中文', 'English')Pick a string by content locale. Fine for two languages; use cms_ui() for more.

Do not print HTML body with two curly braces (it will escape). Use Blade raw: {!! $entry->t('content') !!}. Do not invent a second tag dialect or copy another CMS’s directives.

Group @sanpang