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

Laravel Pug Laravel Package

bkwld/laravel-pug

Adds Pug (formerly Jade) template support to Laravel. Register the .pug extension and write views with Pug's concise, indentation-based syntax—mixins, includes, and layouts included—while Laravel handles rendering and caching. Works alongside Blade templates.

View on GitHub
Deep Wiki
Context7

Getting Started

Install

composer require bkwld/laravel-pug

Laravel 5.5+ auto-discovers Bkwld\LaravelPug\ServiceProvider. On older Laravel versions (or Lumen), register the provider manually in config/app.php / bootstrap/app.php.

Publish the config (recommended)

php artisan vendor:publish --provider="Bkwld\LaravelPug\ServiceProvider"

This creates config/laravel-pug.php. The options in this file are passed through to the underlying Phug renderer, so this is the first place to look when you need to change caching, pretty-printing, extensions, or include paths.

First view

Create resources/views/hello.pug:

doctype html
html
  head
    title Hello
  body
    h1 Hello #{name}

Route/controller as usual:

Route::get('/', fn () => view('hello', ['name' => 'World']));

The package registers the .pug extension with Laravel's view finder, so view('hello') resolves hello.pug exactly like hello.blade.php would.

First real use case

Pick the smallest page in your app (a static marketing page, error page, or auth screen) and port it first. You will immediately exercise layout inheritance, data passing, and the compiled-view cache — the three areas that cause the most friction.

Where to look first

  • config/laravel-pug.php — renderer options.
  • storage/framework/views — compiled Pug output (this is what PHP actually executes).
  • The Phug documentation, since the package is a thin integration layer over phug/phug.

Implementation Patterns

Layouts and sections

Use Pug's native inheritance rather than trying to emulate Blade:

//- resources/views/layouts/app.pug
doctype html
html
  head
    title= title ?? 'App'
    link(rel="stylesheet" href=asset('css/app.css'))
  body
    block content
//- resources/views/dashboard.pug
extends layouts/app

block content
  h1 Dashboard
  p Welcome back, #{user.name}

Partials and components

include partials/nav
include partials/footer

For repeated markup, mixins are the closest thing to Blade components:

//- resources/views/mixins/card.pug
mixin card(title)
  .card
    .card__title= title
    .card__body
      block
include mixins/card

+card('Stats')
  p 42 active users

Passing data and iterating

Data flow is identical to Blade — view('posts.index', compact('posts')) — but the template syntax is different:

each post in posts
  article
    h2= post.title
    p= post.excerpt
else
  p No posts yet.

if user.isAdmin
  a(href=route('admin.dashboard')) Admin

Calling Laravel helpers

Phug expressions are PHP, so framework helpers work directly inside attributes and output expressions:

a(href=route('profile', ['user' => $user->id])) Profile
img(src=asset('img/logo.svg') alt="Logo")

For HTML-producing helpers (csrf_field(), method_field()), use the unescaped operator:

form(method="POST" action=route('posts.store'))
  != csrf_field()
  input(type="text" name="title")

Compiled-view caching

Compiled templates land in storage/framework/views, and Laravel's normal view cache applies. In local development, edits are recompiled on demand. In production, deploy with:

php artisan view:cache

which precompiles both Blade and Pug views.

Front-end asset workflow

bkwld/laravel-pug only handles server-side rendering. If you also want .pug sources compiled for the front end, pair it with a Mix/Webpack Pug plugin; keep the two pipelines' include paths aligned so partials resolve in both.

Gotchas and Tips

Allow Phug 2 (2.5.0) is additive, not breaking

Release 2.5.0 only broadens the Composer constraint on the underlying engine to permit phug/phug v2 as well as the previous line. Existing installs are unaffected unless you explicitly upgrade Phug. Two practical consequences:

  • You can now adopt Phug 2 without waiting on a package release — useful if another dependency requires it.
  • Phug 2 is a major version of the engine. Attribute formatting, escaping defaults, and some extension APIs can differ from Phug 1. After upgrading, diff a few rendered pages (especially forms and anything using raw HTML) and re-run any custom Phug extensions/keywords.

Pin phug/phug in your composer.json if you need deterministic output across deploys.

View name resolution surprises

view('home') prefers whichever extension Laravel finds first. If both home.blade.php and home.pug exist, you can get the wrong one. During migrations, rename or delete the old Blade file rather than leaving both.

Blade directives do not exist

@extends, @include, @csrf, @auth, {{ }} — none of these work. Use extends, include, != csrf_field(), if (auth()->check()), and #{} / !{} respectively. A grep for @ and {{ in converted templates catches leftover Blade syntax quickly.

Caching bites in three places

  • Compiled views: php artisan view:clear
  • Config: php artisan config:cache after editing config/laravel-pug.php
  • Route/config caches interact with package discovery — after adding or removing the package, re-run php artisan optimize:clear

If a Pug change is not appearing, clear the view cache before debugging anything else.

Escaping is a real XSS surface

#{value} escapes; !{value} and != do not. It is easy to reflexively use != for helpers and then reuse the pattern for user data. Audit every unescaped output — especially in comments, profiles, and anywhere users control text.

Debugging is one level removed

Runtime errors point at the compiled PHP file in storage/framework/views, not the .pug source. Open the compiled file to map the failing line back, or enable pretty output in the config so the generated markup is readable. Phug's own error pages are more informative than Laravel's generic view exception, so check the compiled file before assuming a data problem.

Include paths and namespaced views

include partials/nav resolves relative to the configured view paths. Package views (vendor::foo) need the package's namespace registered as a view namespace as usual; Pug includes do not automatically inherit Laravel's namespace resolution, so prefer explicit paths for cross-package partials.

Performance

Compiled templates are plain PHP, so steady-state rendering is fast. The cost is compile time on cache misses and the memory overhead of the Phug renderer. If a hot endpoint feels slow in local dev, verify you are hitting the compiled cache rather than recompiling per request.

Extension points

Custom Pug keywords, filters, and extensions are configured through the renderer options in config/laravel-pug.php. This is the right place to add project-specific shorthands (e.g. a money filter), but treat them as application code: document them and make sure the Phug version constraint you pin supports the APIs you use.

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