The Basics
JCC Blade
Introduction
JCC Blade is the Laravel-style template engine included with jcc-express-mvc. Templates use the extension you configure (often .blade.html under resources/views). Render them with res.render / view() — see Views for app wiring.
Everything below is directive usage: copy the patterns into your templates and adjust names to match your controller data and view paths.
Output
Escaped (safe for user-controlled text):
Raw HTML (only for trusted content):
Dot paths may include spaces around . if you prefer. Inside {{ }} you can use whitelisted methods (for example {{ items.join(', ') }}, {{ name.toUpperCase() }}).
Layouts: @extends, @section, @yield
Child view (e.g. resources/views/posts/index.blade.html):
Layout (e.g. resources/views/layouts/app.blade.html):
Use dot paths without the file extension in quotes: "layouts.app" → layouts/app.blade.html under your views root.
Partials: @include and variants
Conditional includes:
Paths use the same dot notation as res.render.
Stacks: @push, @prepend, @stack
From any view that extends or includes the layout:
The layout prints them with @stack("scripts") and @stack("styles") where those names match.
Conditionals
@if / @elseif / @else / @endif
Conditions may use comparisons (==, !=, ===, >, <, >=, <=) and dotted paths such as user.role.
@unless
@isset / @empty
@switch
@ternary
The condition must be a simple identifier or dotted path (no function calls). The branches are parsed as Blade/HTML.
Loops
@foreach
The loop object exposes index (0-based), first, last, count, even, and odd. The current item also gets loopIndex (same as loop.index).
@forelse (empty fallback)
@for
Optional step: @for (i, 0, 10, 2).
@while
@while (condition) … @endwhile re-evaluates condition against the same template data each time (hard cap 10 000 iterations). The context is not updated between passes, so most repeating markup should use @for or @foreach instead.
Environment
Auth helpers
The engine looks for an Auth property on the template data (same object you pass to res.render / view(), merged with res.locals). It is not wired automatically to req.user; expose something like Auth: req.user (or your session user) when rendering, or use a view composer/middleware that sets res.locals.Auth.
@guest runs when Auth is empty or missing. @auth("role") matches Auth.role, Auth.roleType, or Auth.isAdmin depending on your shape.
Forms: @csrf and @method
Use with csrf() and methodSpoofing in your HTTP kernel (CSRF-protection.md, Middleware.md).
old is set on res.locals when the framework flashes previous input after validation errors (Request.md). @method accepts the verb in quotes, e.g. "PUT", "PATCH", "DELETE".
JSON, assets, Vite, Inertia
For Vite scripts, public/hot, the manifest, and @viteReactRefresh, see Asset-bundling.md. For Inertia setup and SSR, see Getting-Started/Frontend.md.
Raw blocks: @verbatim
Content inside is not parsed as Blade (useful for {{ in docs or client-side templates):
@js … @endjs (server-side)
@js runs JavaScript on the server inside a node:vm context. The template’s data object is copied into a sandbox, the block runs, then properties from the sandbox are merged back into the live template context. The block produces no HTML by itself—use it to compute values you reference later with {{ }}.
The engine strips leading const / let / var from the block so assignments tend to land on the sandbox (see handleJs in index.ts). Errors are logged to the console and do not throw out of the template by default.
Security: this is arbitrary code execution. Only use @js in templates you fully trust (your own view files), never in user-supplied strings.
@script (client-side markup)
@script … @endscript wraps the inner content in a <script> … </script> tag. The inner text is still parsed as Blade, so you can inject values with {{ }}:
@script("path") (quoted path) pulls a file from resources/js/, using dot segments as directories. If the path has no extension, .jsx is appended (for example @script("pages.dashboard") → resources/js/pages/dashboard.jsx). The resolved asset is passed through the same asset pipeline helper as other script tags (see handleScriptPath in the engine).
Errors and performance
Template parse/runtime errors may throw TemplateError with line/column when available. In production, merged layouts for @extends are cached until template files change (mtime).