Forte: Parse &amp; Rewrite Laravel Blade Templates | Mohamed Said        [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com) [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles  ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

       [  ](https://github.com/EG-Mohamed)       

 [ Home ](https://www.msaied.com) [ Projects ](https://www.msaied.com/projects) [ Articles ](https://www.msaied.com/articles) [ Certificates ](https://www.msaied.com/certificates) [ Contact ](https://www.msaied.com#contact-section) 

  [ home ](https://www.msaied.com)    [ articles ](https://www.msaied.com/articles)    Forte: Parse and Rewrite Laravel Blade Templates with a Typed Syntax Tree        On this page       1. [  What Is Forte? ](#what-is-forte)
2. [  Installation ](#installation)
3. [  Parsing Blade Files ](#parsing-blade-files)
4. [  Querying the Tree ](#querying-the-tree)
5. [  Rewriting Templates ](#rewriting-templates)
6. [  Practical Use Cases ](#practical-use-cases)
7. [  Auditing Views Before Deleting a Component ](#auditing-views-before-deleting-a-component)
8. [  Bulk Codemods ](#bulk-codemods)
9. [  CI Convention Checks ](#ci-convention-checks)
10. [  Ecosystem: Chisel and Reload ](#ecosystem-chisel-and-reload)
11. [  Key Takeaways ](#key-takeaways)

  ![Forte: Parse and Rewrite Laravel Blade Templates with a Typed Syntax Tree](https://cdn.msaied.com/623/486e2dce5130f1082093684a345ce5ef.png)

 [  Laravel ](https://www.msaied.com/articles?category=laravel) [  Composer Pacakge ](https://www.msaied.com/articles?category=composer-pacakge)  #Laravel   #Blade   #Parser   #Codemod   #PHP   #Packages  

 Forte: Parse and Rewrite Laravel Blade Templates with a Typed Syntax Tree 
===========================================================================

     1 Sep 2026      4 min read    ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said  

       Table of contents

  11 sections  

1. [  01   What Is Forte?  ](#what-is-forte)
2. [  02   Installation  ](#installation)
3. [  03   Parsing Blade Files  ](#parsing-blade-files)
4. [  04   Querying the Tree  ](#querying-the-tree)
5. [  05   Rewriting Templates  ](#rewriting-templates)
6. [  06   Practical Use Cases  ](#practical-use-cases)
7. [  07   Auditing Views Before Deleting a Component  ](#auditing-views-before-deleting-a-component)
8. [  08   Bulk Codemods  ](#bulk-codemods)
9. [  09   CI Convention Checks  ](#ci-convention-checks)
10. [  10   Ecosystem: Chisel and Reload  ](#ecosystem-chisel-and-reload)
11. [  11   Key Takeaways  ](#key-takeaways)

       What Is Forte?
--------------

Forte (`fortephp/forte`) is a Laravel package written by John Koster that parses `.blade.php` files into a typed syntax tree. Instead of running a regex or a `sed` one-liner that blindly matches every occurrence — including ones inside comments, strings, and unrelated attributes — Forte gives you a structured document you can query and rewrite with precision.

Version 3 of `prettier-plugin-blade` (Chisel) is built on Forte, and the project reports it formats complex real-world templates 140 times faster than the previous version.

Installation
------------

Forte requires PHP 8.2, the `ext-dom` extension, and Laravel 10–13:

```bash
composer require fortephp/forte

```

The service provider auto-registers, so the `Forte` facade is available immediately.

Parsing Blade Files
-------------------

```php
use Forte\Facades\Forte;

$doc = Forte::parse('Hello, {{ $name }}!');
$doc = Forte::parseFile('resources/views/welcome.blade.php');

```

Both methods run a lexer and a tree builder. If a template has an unclosed tag or an `@if` with no `@endif`, the parser records a diagnostic and returns a partial tree — the other files in your project still parse normally. Rendering a parsed file back without changes produces identical bytes, whitespace included.

Querying the Tree
-----------------

Query methods return lazy Laravel collections:

```php
$forms        = $doc->queryElements('form');
$conditionals = $doc->queryBlockDirectives(['if', 'unless']);
$components   = $doc->queryComponents(['x-alert', 'livewire:*']);

```

Forte builds a `DOMDocument` internally and exposes XPath queries. Blade constructs become elements in a `forte` namespace, so `@if` is `forte:if` and `{{ }}` echoes are `forte:echo`:

```php
$divs        = $doc->xpath('//div[@class]')->get();
$conditionals = $doc->xpath('//forte:if')->get();

```

Matches come back as Forte nodes, not raw `DOMElement` objects, so you can pipe them straight into a rewrite.

Rewriting Templates
-------------------

`rewriteWith()` accepts a closure that receives a `NodePath` — an object that exposes the node's parent, siblings, ancestors, depth, and mutation methods:

```php
use Forte\Rewriting\NodePath;

$newDoc = $doc->rewriteWith(function (NodePath $path) {
    if ($path->isTag('a') && str_starts_with($path->getAttribute('href') ?? '', 'http')) {
        $path->setAttribute('target', '_blank');
        $path->setAttribute('rel', 'noopener noreferrer');
    }
});

echo $newDoc->render();

```

Edits are queued and applied in a single pass, so a large template produces one new document rather than one per mutation. For longer logic, write a `Visitor` class with `enter()` and `leave()` methods. A `Builder` helper creates new nodes to insert:

```php
use Forte\Rewriting\Builders\Builder;

Builder::element('div')->class('wrapper')->text('Hello');
Builder::directive('if', '($show)');

```

Practical Use Cases
-------------------

### Auditing Views Before Deleting a Component

```php
$uses = Forte::parseFile($file->getPathname())
    ->queryComponents(['x-alert'])
    ->count();

```

Unlike `grep`, this count excludes mentions inside comments, `@php` strings, and unrelated class attributes.

### Bulk Codemods

Adding `loading="lazy"` to every `` without that attribute across hundreds of views is a single `rewriteWith()` pass. An `` inside a comment parses as a different node kind, so `isTag('img')` is false for it — no accidental matches.

### CI Convention Checks

```php
$missing = Forte::parseFile($file->getPathname())
    ->xpath('//form[@method="POST"][not(.//forte:csrf)]')
    ->count();

```

That XPath expression finds every `POST` form with no `@csrf` anywhere inside it. Drop it in a Pest or PHPUnit test to fail the build automatically.

Ecosystem: Chisel and Reload
----------------------------

- **Chisel** (`prettier-plugin-blade` v3) — Blade formatter built on Forte; requires Node 18+.
- **Reload** (`fortephp/reload`) — experimental Vite plugin that patches Blade changes into the page without a full refresh, falling back after a configurable number of incremental patches.

Key Takeaways
-------------

- Forte parses Blade into a typed syntax tree, avoiding false positives that plague regex-based tools.
- XPath queries use a `forte:` namespace for Blade-specific constructs (`forte:if`, `forte:echo`, `forte:csrf`, etc.).
- Rewrites are non-destructive: `rewriteWith()` returns a new `Document` and leaves the original intact.
- Partial parse results and diagnostics mean one broken template never blocks the rest of your codebase.
- Best suited for structure-dependent rules, large-scale codemods, and automated CI checks — not for one-off renames where `sed` is faster.

Forte is MIT licensed and currently at v1.1.0. Source and docs: [fortephp.com](https://fortephp.com) | [GitHub](https://github.com/fortephp/forte).

---

*Source: [Forte: Parse and Rewrite Laravel Blade Templates — Laravel News](https://laravel-news.com/forte-blade-parser)*

 Found this useful?

          [  ](https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Fforte-parse-and-rewrite-laravel-blade-templates-with-a-typed-syntax-tree&text=Forte%3A+Parse+and+Rewrite+Laravel+Blade+Templates+with+a+Typed+Syntax+Tree) [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.msaied.com%2Farticles%2Fforte-parse-and-rewrite-laravel-blade-templates-with-a-typed-syntax-tree) 

 Frequently Asked Questions 
----------------------------

  3 questions  

     Q01  How is Forte different from using grep or sed to find and replace Blade template content?        Forte parses templates into a typed syntax tree, so queries and rewrites only match real rendered nodes. A grep or sed command also matches occurrences inside comments, PHP strings, and unrelated attributes. Forte's `isTag()` and XPath queries are false for those node kinds, eliminating accidental matches. 

      Q02  Does Forte break if a Blade template has a syntax error?        No. When the parser encounters an unclosed tag or an unmatched directive like `@if` without `@endif`, it records a diagnostic on the document and returns a partial tree. The rest of your templates parse normally, and you can still query and rewrite the partial tree. 

      Q03  When should I use a Visitor class instead of a rewriteWith() closure?        Use a closure for short, self-contained changes. Write a Visitor when the logic is longer or needs both `enter()` (before children are visited) and `leave()` (after children are processed) hooks — for example, when a change depends on what happened to a node's children. 

  Continue reading

 More Articles 
---------------

 [ View all    ](https://www.msaied.com/articles) 

 [ ![Laravel New in 13: Features, Helpers, and Upgrade Notes](https://cdn.msaied.com/625/629cfac34ade7206a215809c0438c5ae.png) laravel php upgrade 

### Laravel New in 13: Features, Helpers, and Upgrade Notes

Laravel 13 ships with async-first primitives, tightened type contracts, and quality-of-life helpers that rewar...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 3 Sep 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-new-in-13-features-helpers-and-upgrade-notes) [ ![Statamic Sidecar: Edit Markdown Sites from the Control Panel Without Migration](https://cdn.msaied.com/624/6df15b406d700ea26fb98c6ad4779195.png) Statamic Markdown CMS 

### Statamic Sidecar: Edit Markdown Sites from the Control Panel Without Migration

Statamic's new Sidecar product lets you manage any static site generator's Markdown files through the Statamic...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 2 Sep 2026     3 min read  

  Read    

 ](https://www.msaied.com/articles/statamic-sidecar-edit-markdown-sites-from-the-control-panel-without-migration) [ ![Laravel Macro-Free Extensibility: Extending Eloquent Builder with Custom Query Objects](https://cdn.msaied.com/621/b0c176a363378658e83bb44ed379879b.png) laravel eloquent clean-architecture 

### Laravel Macro-Free Extensibility: Extending Eloquent Builder with Custom Query Objects

Skip global macros and reach for typed, testable query objects that encapsulate reusable Eloquent constraints...

  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MJ.jpg)  Mohamed Said 

 2 Sep 2026     1 min read  

  Read    

 ](https://www.msaied.com/articles/laravel-macro-free-extensibility-extending-eloquent-builder-with-custom-query-objects) 

   [  ![Mohamed Said](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png)   Mohamed Said Laravel Backend Engineer  ](https://www.msaied.com)Senior Backend Engineer specializing in Laravel, scalable SaaS platforms, APIs, and cloud infrastructure. I build secure, high-performance web applications that help businesses grow.

Explore

- [Home](https://www.msaied.com)
- [Projects](https://www.msaied.com/projects)
- [Articles](https://www.msaied.com/articles)
- [Certificates](https://www.msaied.com/certificates)
- [Contact](https://www.msaied.com#contact-section)

Connect

- [   hello@msaied.com ](mailto:hello@msaied.com)
- [   +20 109 461 9204 ](tel:+201094619204)

© 2026 Mohamed Said. All rights reserved.

 [  ](https://github.com/EG-Mohamed) [  ](https://www.linkedin.com/in/msaiedm/) [  ](https://wa.me/201094619204) [  ](mailto:hello@msaied.com) [  ](https://drive.google.com/file/u/0/d/1MF20IPRJyzfy32mhEutjL5EpSls0w2Q8/view)
