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

treestoneit/html

TreestoneIT HTML gives Laravel and PHP developers a fluent, chainable API for generating HTML elements, attributes, and nested markup in code, keeping views clean and output consistent. It integrates smoothly with Blade and existing templates.

View on GitHub
Deep Wiki
Context7

Getting Started

Use it for one thing: dropping a read-only block of HTML into a Nova resource — a link, a badge, a help banner, an embed. It is a display-only field, not a storage field, and it is not a general-purpose card or layout tool. On Nova 3+ you can usually replace it with Text::make('...')->asHtml(), so treat this package as a fit for older Nova installs or as a stopgap.

Install. The package is archived and effectively unmaintained since 2018-08, so Packagist resolution may fail. If composer require treestoneit/html errors out, pull it from VCS and pin a commit:

"repositories": [
  { "type": "vcs", "url": "https://github.com/treeStoneIT/nova-html" }
],
"require": {
  "treestoneit/html": "dev-master#<commit-sha>"
}

Then confirm what you actually got:

composer show treestoneit/html
ls vendor/treestoneit/html

Look here first, in this order:

  1. src/ — the field class and service provider. Note the exact namespace (TreeStoneIT\Html\...-style, casing matters on case-sensitive filesystems) and whether the provider registers assets via Nova::script()/Nova::style() or $this->publishes().
  2. resources/js/field.js — the Vue component. Its props array tells you the fluent setter name. If the prop is html, the setter is the html() macro; if it's content, it's content().
  3. dist/js/field.js — the compiled bundle. Search it for Nova.booting vs app.component. That single grep tells you whether it was written for Nova 1/2 (Vue 2) or is remotely compatible with Nova 4/5.

First use case — a link on the detail page:

use TreeStoneIT\Html\Html; // confirm exact namespace from src/

public function fields(Request $request)
{
    return [
        Html::make('Portal')
            ->html('<a href="https://portal.example.com" target="_blank" rel="noopener">Open portal</a>')
            ->onlyOnDetail(),
    ];
}

If ->html() isn't the method, the fallback always works because Nova fields serialize their meta as props:

Html::make('Portal')
    ->withMeta(['html' => '<a href="...">Open portal</a>']);

Check $field->meta() in tinker to see exactly what prop name the component expects.

Implementation Patterns

Static notice or banner on detail pages. Keep markup out of the resource class by rendering a Blade partial:

Html::make('Billing notice')
    ->html(view('nova.partials.billing-notice', ['user' => $this->resource])->render())
    ->onlyOnDetail()
    ->canSee(fn ($request) => $request->user()->can('billing.manage'));

canSee() is the cleanest way to make the block conditional — the HTML is never sent to the browser when it returns false.

Index-only action column. The field is ideal for a per-row link when you only need one or two static anchors:

Html::make('Stripe')
    ->html('<a href="https://dashboard.stripe.com" target="_blank" rel="noopener">Dashboard</a>')
    ->onlyOnIndex(),

For per-row dynamic URLs, don't fight the field — the HTML string lives in field meta, which is resolved once per field definition. Either:

  • use Nova's Text::make('Stripe')->asHtml()->displayUsing(fn () => "<a href=\"{$this->resource->stripe_url}\">Dashboard</a>") on Nova 3+, or
  • fork the field and add a resolveUsing()-aware setter.

Group and order it like any other field. It composes with Panel, sortable-free fields() ordering, fullWidth(), and help(). Put a long notice in its own Panel so it doesn't sit awkwardly next to input fields.

Keep it out of forms. Because it renders in create/update views by default, always pair it with ->exceptOnForms() or ->onlyOnDetail()/->onlyOnIndex(). A non-editable HTML blob in a form is confusing and does nothing on submit.

Multiple blocks, one resource. Names must be unique; use short internal identifiers (Html::make('docs-link')) so you can reuse the label as a heading inside your own markup.

Embeds and iframes. <script> tags injected via v-html will not execute in Vue. Use an <iframe> (YouTube, Loom, a status page) and set width/height inline, since Nova's utility classes differ by version.

Replacement path. If you outgrow it, generate a local field with php artisan nova:field acme/html — you get the same Vue component shape with your own prop names, plus support for Nova 4/5's asset registration. Copy the ~40 lines you need from vendor/treestoneit/html/src and drop the dependency.

Gotchas and Tips

  • Archived means frozen. No security patches, no Nova 4/5 support. Anything compiled with Nova.booting and Vue 2 will fail to register in Nova 4+ (Vue 3), producing a blank cell and an Unknown custom element warning in the browser console. Test on your exact Nova version before committing.
  • "It renders nothing." Debug in this order: (1) browser console for an unknown-component warning — assets weren't registered/published; (2) $field->meta() — wrong prop name; (3) the dist/ bundle exists and matches resources/js/. Nova packages that never call Nova::script() need a manual php artisan vendor:publish or a nova-components-style registration.
  • This is raw v-html. Never interpolate unescaped user input — a value stored by a low-privilege user becomes stored XSS with admin session privileges. Wrap dynamic pieces in e() (htmlspecialchars) before concatenating.
  • It is not a database column. Don't add it to $fillable, don't attach ->rules(), don't expect sortable() or filterable() to do anything. It won't appear in search, filters, or exports.
  • Field name doubles as a label. There's no reliable hideLabel() in the Nova 1.x era; pass a short, low-noise name and put the human-readable heading inside your own markup (e.g. <h3 class="...">Billing</h3>).
  • Blade partials beat heredocs. Multi-line HTML in a resource class is unreadable and untestable. view('nova.partials.x')->render() also gives you translations and @can checks for free.
  • Nova's CSS is not your CSS. Utility class names shift between Nova majors. Prefer inline style="..." for anything that must survive an upgrade, and always add rel="noopener" alongside target="_blank".
  • Pin the commit. dev-master against an archived repo is stable in practice, but a fork or VCS typo will bite silently. A commit SHA in composer.json makes builds reproducible.
  • Testing. Assert on the field, not the DOM: $this->assertInstanceOf(Html::class, collect((new UserResource($user))->fields(request()))->first()), and assert the meta string contains your expected anchor. Nova's browser-level rendering isn't worth asserting through this package.
  • If you need interactivity (collapsible sections, copy-to-clipboard state, tabs), stop — this isn't the tool. Build a Card or a local field; HTML fields only paint markup.
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.
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle