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

Html Laravel Package

grafite/html

Grafite HTML is a Laravel package that provides a fluent HTML builder and helper utilities for generating markup directly in PHP. It streamlines forms, links, and UI components with a clean, chainable API for Blade views and controllers.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and confirm it actually loads

composer require grafite/html

Before writing a single line against it, open composer.json in the package and check two things: the illuminate/* version constraint (this package predates current Laravel releases, so it may need --with-all-dependencies or it may simply refuse to install), and whether a HtmlServiceProvider is listed under extra.laravel.providers. If auto-discovery is absent, register manually in config/app.php:

'providers' => [Grafite\Html\HtmlServiceProvider::class],
'aliases'   => ['Html' => Grafite\Html\Facades\Html::class],

Where to look first

  1. src/ — the main builder class and any facade. The public methods are the documentation for a package this small.
  2. tests/ — the fastest spec you will get. Assertions like $this->assertEquals('<a href="...">', ...) tell you exact output, whitespace, attribute ordering, and self-closing behaviour, which is where these helpers usually surprise you.
  3. README.md — often the only usage example that exists.

First use case

The realistic win is data-driven markup: a nav, a breadcrumb, a badge/button, a table row — anything you would otherwise build with string concatenation or a tangle of @if in Blade. Start with one partial and render a list of links from a config array, then compare the diff against the Blade you replaced. If the diff isn't clearly shorter, stop there.

Implementation Patterns

Keep generation at the view boundary. Resolve the builder in a controller or view composer and pass the resulting string/object to the view; don't let HTML strings leak into models or services. In Blade:

{!! $breadcrumbs !!}   {{-- only if the object isn't Htmlable --}}

Test whether the return value implements Illuminate\Contracts\Support\Htmlable. If it does, {{ $breadcrumbs }} renders unescaped automatically and you should prefer that — it signals intent better than {!! !!}.

Wrap it, don't sprinkle it. Put every call behind your own thin class or Blade component:

class Ui
{
    public function button(string $label, array $attrs = []): string
    {
        return (string) Html::tag('button', $label, $attrs); // verify method name in src/
    }
}

This costs ten minutes and buys you a one-file migration path when the package goes unmaintained (which, at 2 stars and 0 dependents, is the base case). Define a small HtmlBuilder interface in your app if more than one or two developers will touch it.

Attribute arrays are the main ergonomic win. Pass attributes as associative arrays and merge conditionally:

$attrs = array_merge(['class' => 'btn'], $isPrimary ? ['class' => 'btn-primary'] : []);

Check the package's class-merging behaviour first — naive array_merge will clobber the earlier class key, so most helpers either accept arrays of classes or expect you to join them yourself.

Compose with Blade, don't replace it. Use the package for the repetitive leaf nodes (buttons, links, icons) and keep @foreach, @csrf, @method, and component slots in Blade. Do not attempt to generate forms with it — CSRF token injection and method spoofing belong to Laravel's directives.

Test the output, not the call. Assert on strings:

$this->assertSame('<a class="nav-link" href="/about">About</a>', (string) $html);

Snapshot two or three representative elements into a test so an upgrade (or your own wrapper refactor) fails loudly on whitespace and attribute-order changes.

Gotchas and Tips

Escaping is the whole risk surface. An HTML generator that returns raw markup is an XSS vector the moment user data reaches it. Check src/ for htmlspecialchars/e() on both text content and attribute values — many small helpers escape one and forget the other. Escape at the call site:

Html::link(e($user->name), route('users.show', $user));

Never pass {!! !!}-worthy output through the builder and assume it's safe because "the package handles it."

Empty and boolean attributes. Verify how null, false, and true are treated — you want null to omit the attribute and true to render disabled="disabled" (or bare disabled). If the helper stringifies blindly you'll ship class="" and disabled="", which is invalid-ish HTML and will confuse your CSS selectors.

Auto-discovery and alias collisions. The Html alias is a classic conflict (collective/html used the same name historically). If another package claims it, rename your alias to HtmlBuilder in config/app.php and update call sites. A "Class 'Html' not found" or "target class does not exist" error on a fresh install is almost always missing discovery or a stale composer dump-autoload.

No licence file. NOASSERTION means GitHub could not detect a licence — that is a legal unknown, not a permissive licence. For client or commercial work, get sign-off or fork the code into your own namespace with an explicit licence before it ships. Combined with 0 dependents and no release cadence, assume abandonment: pin an exact version, commit the lockfile, and vendor the source if the feature is load-bearing.

Config publishing. If there is a config/html.php, check whether a publish tag exists. Without one you can't override defaults without editing vendor, which will be wiped on the next composer update. Copy the defaults into your own service provider's mergeConfigFrom instead.

Extension points. If the class uses Macroable, you can add elements without forking:

Html::macro('pill', fn ($text, $tone = 'info') => Html::tag('span', $text, ['class' => "pill pill-{$tone}"]));

If it doesn't, extend the class, bind your subclass to the container interface in a service provider, and keep the facade pointing at your implementation.

Debugging. dd((string) $html) and dd(get_class($html)) answer most questions about why output looks wrong — you are usually looking at a magic __toString, and a null there silently yields "". Also check for trailing whitespace/newlines in tests/ expectations; those strings will show up in assertSee failures.

Consider the native alternative before committing. Laravel now ships Illuminate\Support\HtmlString, Arr::toCssClasses(), and Blade components/@props, which cover most of what this package does with first-party support. Benchmark the package against a 15-line Blade component on your actual first use case — if the component is comparable, take the component and skip the dependency.

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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager