Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cms Fluid Laravel Package

typo3/cms-fluid

Fluid is the templating engine for TYPO3 CMS, providing a readable, HTML-friendly syntax with layouts, sections, partials, and extensible ViewHelpers. It helps developers build dynamic, secure, maintainable frontend templates and integrates tightly with TYPO3's rendering pipeline.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

Installing the package directly in Laravel is possible, but be aware what you're actually installing:

composer require typo3/cms-fluid

This pulls in typo3fluid/fluid (the templating engine itself) plus TYPO3 CMS dependencies (typo3/cms-core, typo3/cms-extbase, etc.). For a pure Laravel app, you almost always want just the engine:

composer require typo3fluid/fluid

Use typo3/cms-fluid only if you are:

  • Integrating a Laravel app alongside an existing TYPO3 instance (e.g., shared templates, shared ViewHelpers), or
  • Explicitly replicating TYPO3's Fluid behavior including its ViewHelpers (which depend on $GLOBALS['TYPO3_CONF_VARS'] and TYPO3's ObjectManager).

Where to Look First

  1. typo3fluid/fluid — the actual rendering engine. Start at Typo3Fluid\Fluid\View\TemplateView.
  2. TemplatePaths — controls where templates, layouts, and partials are discovered.
  3. ViewHelper\ViewHelperResolver — the extension point for adding your own f:*-style helpers.
  4. Cache\SimpleFileCache (or FluidCacheInterface) — Fluid compiles templates to PHP; you need a cache backend.
  5. vendor/typo3/cms-fluid/Resources/Private/Templates/ — example templates you can crib patterns from (layout, section, partial usage).

First Use Case: Render a Fluid Template from a Laravel Controller

use Typo3Fluid\Fluid\View\TemplateView;
use Typo3Fluid\Fluid\Core\Cache\SimpleFileCache;

$view = new TemplateView();
$paths = $view->getRenderingContext()->getTemplatePaths();
$paths->setTemplateRootPaths([resource_path('fluid/templates')]);
$paths->setLayoutRootPaths([resource_path('fluid/layouts')]);
$paths->setPartialRootPaths([resource_path('fluid/partials')]);

$view->getRenderingContext()->setCache(
    new SimpleFileCache(storage_path('framework/fluid-cache'))
);

$view->assignMultiple([
    'title' => 'Hello',
    'items' => ['one', 'two', 'three'],
]);

return response($view->render('Index'));

With resources/fluid/templates/Index.html:

<f:layout name="Default" />
<f:section name="Main">
    <h1>{title}</h1>
    <ul>
        <f:for each="{items}" as="item">
            <li>{item}</li>
        </f:for>
    </ul>
</f:section>

Implementation Patterns

Wrap Fluid as a Laravel View Engine

Register Fluid as a custom view engine so view('fluid::index') works alongside Blade:

// app/Providers/FluidServiceProvider.php
public function register()
{
    $this->app['view']->addExtension('fluid.html', 'fluid');
    $this->app['view']->addExtension('html', 'fluid');
}

public function boot()
{
    $this->app['view']->resolver->addNamespace('fluid', resource_path('fluid'));
}

Then a FluidEngine implementing Illuminate\View\Engines\Engine wrapping TemplateView. This lets you drop Fluid into existing controllers and keep $this->view(...) ergonomics. Because Fluid's assignMultiple is already array-based, this fits Laravel's view($name, $data) cleanly.

Component Reuse — Layouts, Partials, Sections

Fluid's real day-to-day value:

  • Layouts (<f:layout name="Default" />) = Blade's layout + @section.
  • Partials (<f:render partial="Card" arguments="{item: item}" />) = Blade's @include / anonymous components.
  • Sections (<f:section name="Main">) = @yield blocks.

Pattern: keep one layout per domain (e.g., Admin.html, Email.html), and treat every reusable UI block as a partial that takes explicit arguments. Fluid forces you to pass data explicitly rather than reaching into globals — that's a net win for component hygiene.

Bridging TYPO3-Specific ViewHelpers to Laravel

Do not try to use f:link.page, f:uri.action, f:form, or f:be.* inside Laravel — they will throw because they need a TYPO3 request/context. Instead:

  1. Register custom ViewHelpers for Laravel equivalents:
    • f:link.page → write app:route calling route().
    • f:uri.resource → write app:asset calling asset() / Vite::asset().
    • f:translate → wrap __().
  2. Disable or exclude TYPO3's ViewHelper namespaces in your ViewHelperResolver — you don't want a stray f:form in a template blowing up at render time.
$resolver = $view->getRenderingContext()->getViewHelperResolver();
$resolver->addNamespace('app', 'App\\Fluid\\ViewHelpers');

Hybrid Blade + Fluid

Realistic migration pattern: use Fluid for content-heavy, author-edited, or email templates (where its strictness pays off) and Blade for admin/dashboard UI. Set up a dedicated fluid/ view namespace so the two never collide. Migrate partial-by-partial, not template-by-template.

Data Shaping

Fluid templates want arrays/objects with public getters. Eloquent models work for simple properties but:

  • Relationships ($model->posts) need to be pre-loaded and often mapped to plain arrays to keep templates predictable.
  • Collections should be converted with ->toArray() or a presenter so f:for iteration and {item.title} access work without surprises.

Pattern: introduce a Presenter/Resource layer (JsonResource is close) that gives Fluid a flat, deterministic shape.

Caching

Wire Fluid's compiled-template cache to Laravel's storage and clear it with a view:clear override:

// in a deploy/Aritsan command
File::deleteDirectory(storage_path('framework/fluid-cache'));

For high-traffic pages, pre-warm the cache during deploy by rendering critical templates once with dummy data.


Gotchas and Tips

Licensing

typo3/cms-fluid is GPL-2.0. That is a distribution-time concern, and it can bite you hard in commercial/proprietary products. typo3fluid/fluid (the standalone engine) is also GPL-2.0. If you're shipping closed-source software, confirm with legal before adopting. For internal or open-source Laravel apps this is usually a non-issue.

Namespace and Dependency Bloat

typo3/cms-fluid drags in TYPO3 core (TYPO3\CMS\Core, Extbase, ObjectManager, $GLOBALS['TYPO3_CONF_VARS']). This is a large surface area for a Laravel app and can:

  • Pull in symfony/* versions that conflict with your Laravel install.
  • Register TYPO3 autoload prefixes that shadow or collide with project classes.

Tip: If you're not sharing a live TYPO3 instance, depend on typo3fluid/fluid only. You get the same template syntax, ViewHelper API, layouts, partials, and cache — without the CMS.

Cache Invalidation

Fluid compiles each template to a PHP class whose name encodes the template contents. Editing a partial does not automatically invalidate a layout that renders it, and clearing storage/framework/views (Blade's cache dir) does nothing. Point Fluid's cache at its own directory and clear it explicitly in CI/deploy. Stale-cache bugs look like "my change didn't take" and waste hours.

Debugging

  • Parse errors are usually Typo3Fluid\Fluid\Core\Parser\Exception and include template name + line. They do not map to Blade's line-numbered exception page.
  • Missing ViewHelper errors are often a namespace registration mistake, not a syntax bug — check ViewHelperResolver::getNamespaces().
  • Wrap render() in a helper that catches Typo3Fluid\Fluid\View\Exception\InvalidTemplateResourceException and logs the resolved template paths; 90% of "template not found" is a path misconfiguration, not a filename typo.

Template Path Resolution Order

Fluid searches TemplateRootPaths in reverse numeric order ([10, 20] searches 20 first). This lets you override a base template with a project-specific one — same idea as Laravel's package view overrides, but the ordering trips up first-timers.

Escaping and Interpolation

Fluid escapes {variable} by default at the ViewHelper boundary, but not the same way Blade's {{ }} does. Double-braces {{ ... }} in Fluid mean no escaping (raw HTML). If you ported Blade habits into Fluid, audit for accidental unescaped output. Always use {var} or explicit <f:format.raw> only when intended.

Testing

Fluid templates are testable in-process: instantiate a TemplateView, assign fixture data, call renderToString('Index'), and assert on the HTML. This is easier than it looks and worth a small base test case:

public function renderFluid(string $template, array $data): string
{
    $view = new TemplateView();
    // ... configure paths/cache once via test setUp
    $view->assignMultiple($data);
    return $view->render($template);
}

Snapshot-test partials with fixed data — regressions in component output get caught fast.

Extension Points to Know

  • ViewHelperResolver — add, replace, or block namespaces. Your single most important hook when integrating with Laravel.
  • TemplatePaths — per-view override paths for theming/multi-tenancy.
  • FluidCacheInterface — swap in a Redis or Laravel-cache-backed implementation for distributed deploys.
  • RenderingContext — attach a controller name/action, variable container, and error handler. Use it to inject a Laravel-aware f:link implementation without touching templates.

When Not to Reach for It

If the goal is "Blade with different syntax," Fluid isn't worth the cost — the GPL license, TYPO3 dependencies, and learning curve are real. Fluid earns its place when you have existing TYPO3 templates/ViewHelpers to share, or you want strict, argument-based, no-magic partials enforced by the engine. For new Laravel apps without a TYPO3 tie-in, stick with Blade + components — you'll get the same server-side rendering outcomes with far less friction.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console