See: https://github.com/EFTEC/BladeOne
This is going to be our next render engine.
BladeOne (eftec/bladeone) is the pragmatic standalone Blade. A single ~5–6k-LOC PHP file, zero Composer dependencies beyond ext-json, ~8.1M installs, v4.19.1 shipped September 2025, regular 2025 releases. As long as you instantiate via new BladeOne(...) and never touch the optional BladeOne::$instance accessor, the engine is genuinely instance-scoped and two instances coexist safely. It supports @php … @endphp, @if/@foreach/@switch, @extends/@yield/@section, @push/@stack, @class/@style, and the legacy @component('navbar', [...]) … @slot('title') … @endslot … @endcomponent system with named slots.
We need a working file cache for this. We should use the PSR for this.
Example code to establish a render engine pipeline:
interface Renderer {
public function supports(string $viewPath): bool;
public function render(string $viewPath, array $opt): string;
}
trait CanRenderView {
/** @var Renderer[] */
private array $renderers = [];
public function registerRenderer(Renderer $r): void {
$this->renderers[] = $r;
}
public function render(string $viewPath, array $opt = []): string {
$opt = $this->buildOpt($opt); // existing: response/request/root/host/user/title
$opt['e'] = fn($v) => htmlspecialchars((string)$v, ENT_QUOTES|ENT_SUBSTITUTE, 'UTF-8');
$opt['component'] = $this->makeComponentInvoker($opt);
$opt['generateResourceLink'] = $this->generateResourceLinkFor($opt);
$opt['layout_essentials_body'] = $this->layoutEssentialsBody($opt);
$opt['layout_essentials_head'] = $this->layoutEssentialsHead($opt);
foreach ($this->renderers as $r) {
if ($r->supports($viewPath)) {
$body = $r->render($viewPath, $opt);
return $this->wrapInLayout($body, $opt);
}
}
return $this->renderClosureArray($viewPath, $opt); // existing path, unchanged
}
}
See: https://github.com/EFTEC/BladeOne
This is going to be our next render engine.
BladeOne (
eftec/bladeone) is the pragmatic standalone Blade. A single ~5–6k-LOC PHP file, zero Composer dependencies beyondext-json, ~8.1M installs, v4.19.1 shipped September 2025, regular 2025 releases. As long as you instantiate vianew BladeOne(...)and never touch the optionalBladeOne::$instanceaccessor, the engine is genuinely instance-scoped and two instances coexist safely. It supports@php … @endphp,@if/@foreach/@switch,@extends/@yield/@section,@push/@stack,@class/@style, and the legacy@component('navbar', [...]) … @slot('title') … @endslot … @endcomponentsystem with named slots.We need a working file cache for this. We should use the PSR for this.
Example code to establish a render engine pipeline: