Templates and View Data
Every theme template receives a rich, pre-assembled set of variables — the content, site settings, navigation, media and SEO data. This article is the reference for that data and for the rendering rules templates should follow.
How a template is chosen
For content of type page on a site with theme mytheme, Laravix renders themes.mytheme::page.show.
That namespace resolves against your theme first and the default theme second, so the view "exists" as long as either theme provides it. Only when neither does — an unknown content type, say — does Laravix fall back to themes.mytheme::default, which resolves the same way. The same convention applies to every content type, including plugin types.
In practice: to change how posts look, add post/show.blade.php to your theme. To leave them alone, add nothing. See Theme Structure.
Available variables
Assembled by Laravix\Cms\Services\PageDataBuilder and the CMS controller:
| Variable | Type | Contents |
|---|---|---|
$content |
Content |
The content being rendered, with fields and taxonomies loaded |
$site |
Site |
The current site |
$seo |
array |
title, description, og_image_url, noindex, canonical — with content-over-settings fallbacks already applied |
$settings |
Collection |
All site settings as key ⇒ value |
$navigations |
array |
Header/footer menu items, already localized for the current language |
$navDesign |
array |
The design values from the navigation Design tabs |
$logoMedia, $faviconMedia |
?Media |
The logo and favicon from settings, resolved to models |
$mediaMap |
Collection |
id ⇒ Media map of every media referenced by the page |
$navPages |
Collection |
Published pages/archives of the current locale (id, title, slug, is_homepage) — for building simple menus |
$archivePosts |
?Collection |
On archive content only: published posts, newest first |
$grapesjsHtml |
?string |
The visual builder's HTML, already hydrated (post lists filled in, plugin hydrators applied) |
$defaultLocale, $currentLocale |
string |
Locale codes |
$alternates |
Collection |
locale ⇒ absolute URL of published translations (for hreflang) |
$systemFieldKeys |
array |
Keys of code-registered fields — handy to separate them from ad-hoc fields |
$appearance |
Collection |
Per-page appearance overrides. Currently always empty — the default layout reads it for background colour, text colour and a custom CSS class, so a template that uses it must tolerate empty values |
$bgMedia |
?Media |
Background image for the page. Currently always null, read by the default layout alongside $appearance |
Working with media
Media models expose $media->url (the original) and $media->variantUrl(ImageVariant::LARGE) for resized variants (THUMBNAIL, MEDIUM, LARGE, OG, FAVICON, FULL — see Laravix\Cms\Enums\ImageVariant). Always render the smallest variant that fits the slot.
Working with fields
@php $fields = $content->fields->pluck('value', 'key'); @endphp
{{ $fields->get('excerpt') }}
Theme assets
Two helpers turn a file into a URL, both on Laravix\Cms\Laravix:
{{-- The stylesheet bundled with the core, from public/vendor/laravix/ --}}
<link rel="stylesheet" href="{{ \Laravix\Cms\Laravix::asset('app.css') }}">
{{-- A file your theme built into themes/{theme}/dist/ --}}
@if ($themeStylesheet = \Laravix\Cms\Laravix::themeAsset('app.css', $site->theme))
<link rel="stylesheet" href="{{ $themeStylesheet }}">
@endif
themeAsset() takes the file name and the theme key, and returns null when the file isn't in that theme's dist/ — so always guard it as above rather than printing it straight into an attribute. The URL it returns ends with a ?v= stamp derived from the file's modification time, which busts the browser cache whenever you rebuild.
Both resolve to real files under public/, which for themes means the public/themes/{theme} symlink created by php artisan laravix:theme:link. If a theme stylesheet silently doesn't load, that link is the first thing to check.
Rendering builder content
Content designed in the visual builder arrives as $grapesjsHtml. Content built from classic blocks arrives as the $content->blocks array. The core ships a partial that handles both, including the JavaScript that sliders, tabs, countdowns and custom code blocks need:
@include('laravix::cms.builder-content')
The default theme's page/show.blade.php does exactly this when builder content exists, and falls back to a plain title-and-fields layout otherwise. If you render blocks yourself instead, each entry of $content->blocks is ['type' => ..., 'data' => [...]] and maps to your theme view blocks/{type}.blade.php, which receives the block's data plus $mediaMap.
URLs and languages
Build links to other content with $content->path($defaultLocale) — it handles the homepage, route prefixes and locale prefixes. In layouts, emit alternates:
@foreach ($alternates as $altLocale => $altUrl)
<link rel="alternate" hreflang="{{ $altLocale }}" href="{{ $altUrl }}">
@endforeach
SEO contract
Layouts should honor the $seo array: put $seo['title'] in <title>, output the description and canonical link, emit noindex,nofollow robots meta when $seo['noindex'] is true, and use $seo['og_image_url'] for Open Graph. The default theme's layouts/app.blade.php is a complete reference implementation, including Open Graph, Twitter cards and JSON-LD.
Related articles
- Theme Structure
- CLI Commands —
laravix:theme:link - Custom Blocks
- Content Model