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

Tale Jade Laravel Package

talesoft/tale-jade

Tale Jade brings the Jade/Pug templating language to Laravel, compiling concise, indented templates into plain PHP. It offers configurable compiler options, precompilation support, and seamless integration with Laravel's view system for fast, readable views.

Deep Wiki
Context7

Getting Started

Install via Composer:

composer require talesoft/tale-jade

The package is a compiler, not a framework integration. Everything hangs off Jade\Jade, which takes an options array and renders .jade files to HTML:

use Jade\Jade;

$jade = new Jade([
    'cache'     => storage_path('framework/jade'), // compiled PHP lives here
    'pretty'    => false,                          // true = indented HTML, slower
    'extension' => '.jade',
]);

echo $jade->render(resource_path('views/home.jade'), [
    'title' => 'Home',
    'name'  => 'World',
]);

Where to look first:

  1. The Jade\Jade class — render(), renderString(), compile(), compileString(), isExpired() are the entire public surface you'll use day to day.
  2. The options array passed to the constructor (cache, pretty, extension, basedir, expressionLanguage).
  3. The compiler under Jade\Compiler — only when you need to debug generated PHP or write an extension.

First use case: a layout plus one child view. In layout.jade:

doctype html
html
  head
    title= title
  body
    block content

In home.jade:

extends layout
block content
  h1 Hello #{name}

Then $jade->render('home.jade', ['title' => 'Home', 'name' => 'World']). If that works, the rest of the package is variations on this.

If you're wiring it into Laravel, bind a configured Jade instance as a singleton in a service provider rather than new Jade() per request — the compiler is expensive and the cache directory must be consistent across requests:

$this->app->singleton(Jade::class, fn () => new Jade([
    'cache'  => storage_path('framework/jade'),
    'pretty' => config('app.debug'),
]));

(Check whether the version you pull in ships a Laravel bridge/provider; if it does, use it and publish its config instead of hand-rolling the binding.)

Implementation Patterns

Controllers return rendered strings. There's no view-engine contract here, so the common pattern is a thin base controller method or a helper:

return response($this->jade->render('pages/about.jade', compact('user')));

Cache the rendered string yourself (Laravel's Cache::remember) if a page is expensive — Tale Jade only caches the compiled PHP, not the output.

Layout inheritance instead of Blade components. Use extends/block for page skeletons and include for partials (include /partials/nav). basedir controls where absolute includes resolve; set it to resource_path('views') so includes don't depend on the including file's location.

Mixins for reusable UI. This is the closest thing to Blade components and worth standardizing on early:

mixin card(title)
  .card
    h3= title
    block

+card('Recent orders')
  p Nothing yet.

Keep mixins in a single mixins.jade and include it from layouts so ordering is deterministic.

Pick one expression language and stick to it. The expressionLanguage option toggles between JavaScript-flavored (#{name}, each item in items, - var x = 1) and PHP-flavored (#{$name}, - $x = 1) expressions. Mixing conventions across templates produces confusing "undefined variable" failures rather than syntax errors. Decide in the service provider, document it in the repo README, and never let both styles into the codebase.

Precompile in your deploy step. Use compile()/compileString() to generate PHP during build rather than on first request, and use isExpired($file) in a warmup command to compile only what changed. In development, point cache at a local directory and let mtime checks handle invalidation.

Escape deliberately. #{expr} escapes, !{expr} does not. Treat !{} like {!! !!} in Blade: only for values you produced, never for request input.

Gotchas and Tips

  • It's a 2016-era package. Last release August 2016. Expect friction on PHP 8.x: deprecated curly-brace string offsets, each()-style patterns inside the compiler, and dynamic property warnings. Budget time to either pin PHP 7.4 or patch the compiler; test the full template suite on upgrade. If you're starting a new project and only need Pug-like syntax, evaluate current alternatives first — this is a solid implementation, but not a maintained one.
  • Cache invalidation is the #1 support issue. Compiled templates are keyed on source mtime. Deploys that preserve mtimes (rsync -a, some artifact pipelines) will silently serve stale HTML. Clear the Jade cache directory on every deploy, or deploy with checksum-based copying. Note that php artisan view:clear will not touch it — the cache lives wherever you pointed the cache option.
  • Indentation is syntax. Mixed tabs and spaces, or a stray space in an otherwise consistent file, produces parse errors that point at the wrong line. Enforce a .editorconfig with tabs (or spaces) and lint templates in CI by compiling them all.
  • Error messages reference generated PHP. When a runtime error fires inside a compiled template, the stack trace line numbers belong to the cached PHP file, not your .jade. Set pretty => true and open the compiled file to map back; turn pretty off again for production.
  • pretty is a performance and output-fidelity switch. It re-indents HTML, which can change whitespace-sensitive output (inline elements, <pre>). Off in production, and be aware it alters output, not just readability.
  • Extension is configurable but not magic. If you use .jade.php or .pug, set extension explicitly and make sure includes use the configured extension; a mismatch surfaces as "file not found" during include resolution.
  • Extension points are limited. The realistic customization surface is options plus precompilation; there's no documented plugin API worth building on. If you need custom filters or helpers, inject data (closures render as expressions in PHP mode) rather than forking the compiler.
  • No auto-escaping of attribute values in every position. Audit attributes built from user data (a(href=url)) and prefer explicit escaping helpers in the expression rather than assuming the compiler handles it.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
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
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core