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

Blade Laravel Package

leafs/blade

leafs/blade provides reusable Blade components for adding interactive maps to Laravel applications. Drop a component into any view, pass coordinates and markers, and customize the map without writing JavaScript by hand. Lightweight, expressive, and easy to integrate.

View on GitHub
Deep Wiki
Context7

Getting Started

leafs/blade is a thin adapter that lets Leaf PHP render views with the Blade compiler from illuminate/view (it leans on jenssegers/blade for the standalone binding). Treat it as "Blade without Laravel": syntax is identical, the surrounding helpers are not.

v5.0 is a platform bump, not a cosmetic release. Before you install, check two things: PHP 8.2+, and illuminate/view ^11 | ^12 | ^13. If your app or another dependency is still on Laravel 9/10 components, v5 will not resolve — see Gotchas before you try.

Where to look first, in this order:

  1. README.md — the only place the supported constructor signature, Leaf integration snippet, and the new @lingo / @tl directive setup are documented.
  2. src/Blade.php — it is small; read it end-to-end to see exactly which jenssegers/blade methods are forwarded, which are shadowed, and where the Crash breadcrumb hooks are wired in.
  3. composer.json — the illuminate/view and php constraints are the single biggest integration risk in an existing project, and both changed in v5.0.
  4. Your Leaf skeleton's view config (app/config / config/view.php depending on version) — that is where views and cache paths are wired.
  5. leafphp.dev/docs/routing/error-handling — the Leaf Crash docs, now that Blade feeds view breadcrumbs into error reports.

Minimal steps:

php -v                       # must be 8.2+
composer require leafs/blade
composer why illuminate/view # must resolve to ^11 | ^12 | ^13
mkdir -p views storage/cache/views
// views/home.blade.php
<h1>Hello {{ $name }}</h1>
// index.php
require __DIR__ . '/vendor/autoload.php';

use Leaf\Blade;

$blade = new Blade(__DIR__ . '/views', __DIR__ . '/storage/cache/views');
echo $blade->render('home', ['name' => 'Leaf']);

First use case to build: a single authenticated dashboard page with one layout and two partials, plus one string passed through @lingo. That exercises the things you actually need to validate — layout inheritance, cache directory writability, data passing, and whether Lingo is correctly wired for the new directives — before you commit to migrating a whole app's templates. Then throw a deliberate exception inside a partial and confirm the view appears in the Leaf Crash report with a duration; that is the headline v5.0 feature and you want to know it works before you are debugging an outage.

If you are on Leaf 3, the idiomatic wiring is to attach the engine to Leaf's view layer once at bootstrap (View::attach(\Leaf\Blade::class, 'blade') or the equivalent in your Leaf version) and then call View::render('home', $data) from routes. Confirm the exact call against the README for your installed tag; the attach API has moved between Leaf majors.

Implementation Patterns

Engine registration at bootstrap. Attach Blade once, in index.php or a service provider, before any route runs. Do not instantiate a new Blade per request unless you deliberately want a cold compiler — the compiler holds resolved view state and re-instantiating throws that away. This matters more in v5: a single shared instance is also what gives Leaf Crash a coherent chain of breadcrumbs for the request.

Layout + partials, the standard shape.

{{-- views/layouts/app.blade.php --}}
<html><body>
  @include('partials.nav')
  @yield('content')
</body></html>
{{-- views/dashboard.blade.php --}}
@extends('layouts.app')
@section('content')
  <p>Signed in as {{ $user['name'] }}</p>
@endsection

Translations with @lingo / @tl. v5.0 adds first-class directives for Leaf Lingo. Keep translation keys in templates and all copy in Lingo's store — do not hardcode English strings "for now", because the moment you have two locales you will be grepping templates instead of language files.

{{-- verify exact argument shape against the README for your tag --}}
<h1>@lingo('dashboard.title')</h1>
<p>@tl('dashboard.greeting', ['name' => $user['name']])</p>

If Lingo is not installed and configured, these directives have nothing to compile to — establish the Lingo bootstrap before the Blade engine so the compiled PHP can resolve its translator at render time. See Gotchas.

Let Leaf Crash do the work. The breadcrumb trail (which views rendered, in what order, and how long each took) is emitted automatically on every render. You do not need to instrument your templates. The pattern that pays off is making sure your error handler actually surfaces the report in non-production environments, then reading the trail to find the slow or repeated view, not just the failing one — a partial rendered 40 times in a loop is usually the real cost centre.

Shared data instead of repeating yourself. Anything needed by every view (current user, app name, flash messages) belongs in one place. If the wrapper exposes share()/shareData(), use it after construction; if it does not, write a small ViewData class that merges base data into the array you pass to render(). That second option is more portable and survives a swap of the package.

$blade->share('appName', 'Acme'); // verify availability in src/Blade.php
echo $blade->render('dashboard', ['user' => $user]);

Custom directives as your escape hatch. The moment you need loop counters, money formatting, or environment badges, register a directive rather than dropping to {!! !!} with hand-built HTML:

$blade->directive('money', fn ($expr) => "<?php echo number_format($expr, 2); ?>");

Middleware-driven view data. In Leaf, push shared view data from middleware (auth, locale, flash) so controllers stay thin and every template sees a consistent set of variables. Locale-in-middleware pairs naturally with @lingo: set the locale once per request, and every @lingo string in every view follows.

Testing. Point Blade at tests/fixtures/views and tests/fixtures/cache and assert on rendered strings. Keep the fixture cache directory out of git and wipe it in setUp() so a stale compiled file never masks a failing test. v5.0 moves the upstream suite to Alchemy, which is an internal detail — it is a maintenance signal, not something you need to adopt. Add one test that asserts a @lingo key renders translated text; that is the regression most likely to slip through.

Deployment rhythm. Compile-on-first-request is fine in dev; in production warm the cache during deploy (render each top-level view once in a script) and ship the compiled directory alongside the code, or accept one slow request per view per release. On a major bump like 5.0, wipe the cache directory before warming — compiled files from v4 are not something you want served.

Gotchas and Tips

  • v5.0 drops Laravel 9/10 and PHP < 8.2. illuminate/view ^11 | ^12 | ^13 plus PHP 8.2+ is a hard floor. Any app still pulling illuminate/* at 9 or 10 cannot install this version, and any host on PHP 8.0/8.1 cannot run it. Run composer why illuminate/view before and after installing, and check php -v in CI as well as locally — the CI image is where this bites.
  • Laravel helpers do not exist. @csrf, @auth, @guest, @can, route(), asset(), old(), csrf_field() will all fatal with "undefined function" the first time a template renders. Either define plain PHP functions with those names in a bootstrap file, or (better) ban the directives in your templates and pass raw values in. Note that @lingo and @tl are not in this list only because this package registers them — every other Laravel directive still is.
  • @lingo / @tl without Lingo is a blank-page class of failure. Confirm Leaf Lingo is required, bootstrapped before the view engine, and has a translator available at render time. If the directive compiles to a call that cannot resolve, you get the same silent white output as any other compile/render failure. Test one translated string in isolation before rolling translations across templates.
  • Relative paths break under different working directories. A queue worker, a CLI command, and a web request have different CWDs. Always build view and cache paths from __DIR__ or base_path(); never from bare 'views'.
  • Cache directory permissions and staleness. The compiler writes PHP files into the cache path. Not writable → blank page or a swallowed exception. Writable but stale (deploy overwrote views, cache untouched) → you debug code that is no longer in the file. Clear the cache directory on every deploy; there is no view:clear command here.
  • Debugging technique: open the compiled file in the cache directory. Blade maps dashboard.blade.php to a hashed filename, but the compiled PHP is readable and shows exactly what a directive expanded to — including what @lingo became — far faster than guessing at @ syntax. Pair this with the Leaf Crash breadcrumb trail: the trail tells you which view, the compiled file tells you why.
  • {{ }} escapes, {!! !!} does not. With no framework-level sanitisation layer, every {!! !!} is a deliberate XSS decision. Audit them; you will find more than you expect after a Laravel migration, because Laravel apps often rely on helpers that sanitise downstream.
  • Blank pages mean compile failures, not view logic. With display_errors off, a missing @endsection or an unclosed @if yields white output. Check error_log first, then read the Leaf Crash report — if the breadcrumb trail stops before the view you expected, the failure is in compilation, not in your data.
  • Breadcrumbs accumulate per render — check long-lived workers. If you run under a persistent worker (queue daemon, Swoole/Octane-style server), verify that the breadcrumb buffer is reset between jobs/requests in your version. A trail that grows across requests is a slow memory leak and makes error reports nonsensical. If it is not reset, clear it manually or rebuild the engine per job.
  • Extension expectations. Confirm whether the adapter resolves home to home.blade.php or home.php in your version; a mismatch shows up as "view not found" even though the file plainly exists. The compiler's exists() check is the fastest way to prove the path is wrong rather than the name.
  • Maintenance risk is still real. Four stars and zero dependents means no crowd-sourced bug triage, and v5.0 shows the package tracking Laravel majors closely — which means another breaking platform bump is a when, not an if. Pin the exact version ("leafs/blade": "5.0.*"), and isolate usage behind your own View facade or a one-file Template class so replacing the engine is a contained change rather than a grep across the codebase.
  • Extension points worth knowing: custom directives, custom if statements, shared data, the Compiler instance itself if you need to register component-style tags, and now @lingo / @tl. Everything else is upstream Blade behaviour and should be looked up in the illuminate/view docs, not here.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource