bnussbau/laravel-trmnl
Laravel integration for TRMNL e-ink displays. Build custom plugins and screens in Laravel, expose data through routes, and render Blade views for your TRMNL device using a simple, familiar API.
Architecture fit. bnussbau/laravel-trmnl is a thin presentation-layer adapter: it gives a Laravel app the routes, config, and Blade rendering primitives needed to serve a screen payload to a TRMNL e-ink device, which polls a URL on a schedule and renders the returned markup. It sits at the edge of the architecture, alongside other "output channel" adapters (mail, PDF, webhooks), and requires no changes to domain models or persistence. Coupling is therefore low, and the package is replaceable with a hand-rolled controller returning the same markup if needed. The 2.3.0 release does not change that posture — it is a compatibility-and-dependency release, not a feature release.
Release 2.3.0 delta. Two things matter for a decision:
composer.json before assuming a safe upgrade.bnussbau/laravel-trmnl-blade ^2.3.4 → ^3.0.3 and voku/simple_html_dom ^4.8 → ^5.0. The Blade package is the view/component layer that actually produces the markup; a major bump there is the highest-risk item in this release, since component names, slots, and published view stubs are the public surface a consumer touches. The simple_html_dom major is lower risk if it is only exercised in parsing helpers, but it is a genuine breaking-change signal if it appears in the request path. Both landed via Dependabot, which means the package's own test suite is the only gate — and a solo-maintainer project with automated dependency PRs deserves a check of what that suite actually covers.Technical risk. Moderate, concentrated in the Blade dependency rather than in the package itself. Specific hazards: silently stale published views if 3.x changed stubs (a re-publish would overwrite local customizations); signature or output-format drift in the rendered markup that passes unit tests but looks wrong on a 1-bit e-ink screen; and an unverified PHP floor implied by Laravel 13. Secondary risk is governance: single maintainer, high bus factor, dependency churn driven by bots rather than a roadmap. That is acceptable for an output adapter but argues against letting it own any business logic.
Key questions.
laravel-trmnl-blade 3.x change component/view names, config keys, or published stubs, and is there a documented upgrade note?simple_html_dom used when serving a screen request, or only in tooling/tests?Stack fit. Clean fit for any Laravel 10+ application already using Blade. Installation is Composer-only, configuration is a published config file, and the integration point is a single route the device polls. No queue, no database migration, no service provider of ours to write. It composes naturally with existing auth middleware if the screen exposes internal data.
Sequencing.
composer.json constraints rather than trusting the release title.laravel-trmnl-blade to 3.x in a branch, re-publish views to a temp path, and diff against the locally published copies before adopting the parent bump. This is the step most likely to surface breakage, and doing it separately keeps the failure attributable.simple_html_dom usage. If it is only reachable from tests or an admin-side preview, accept 5.0 with a smoke test and move on. If it is in the screen-serving path, add a rendering test asserting the output structure before upgrading.Compatibility. Treat the two major dependency moves as the compatibility question and Laravel 13 support as a bonus. If the app is on Laravel 11 or 12, the correct read of 2.3.0 is "our version still works and the package is alive," not "we should upgrade today." If the app is on Laravel 12 and planning 13, this release is the enabling dependency and should be sequenced ahead of the framework upgrade, not after it.
Migration path. Low-cost and reversible. The package is an adapter, so the fallback is a controller that returns the same markup. Keep the screen-producing logic in our own class (a view model or dedicated presenter) rather than in the package's Blade components, so a future swap — or a repeat of this kind of major-dependency churn — is a routing change rather than a rewrite.
Maintenance. Low ongoing effort: one dependency, no schema, no daemon. The real maintenance cost is attention, not labor — Dependabot noise (this release contains three CI-only bumps that carry no runtime meaning) will generate review load disproportionate to the package's importance. Set the expectation that most releases are dependency housekeeping and triage accordingly; a monthly review cadence is sufficient unless a major lands.
Support and bus factor. Single maintainer, no stated support policy, no LTS. Acceptable because the blast radius is a single read-only endpoint and the replacement cost is small. Do not escalate issues upstream expecting SLAs; plan to fork or vendor the rendering layer if the package goes quiet, and record that decision now rather than during an incident.
Scaling. Negligible. TRMNL devices poll on the order of minutes, not seconds, so request volume is trivially low even across many devices. Two things do scale: the rendering cost per request (template compilation, any upstream data fetches) and the thundering-herd effect if many devices share a poll window. Mitigate by caching the rendered payload with a TTL slightly under the poll interval and serving from cache; that also decouples device availability from upstream data-source latency.
Failure modes.
Ramp-up. Under a day for a Laravel developer: install, publish, define a route, point a device at it, iterate on the Blade template. The non-obvious learning is e-ink design constraint — no color, no animation, limited refresh — which is a design skill rather than a Laravel one. Budget a short spike with the device or TRMNL's preview tool before committing to a layout, and document the screen's data contract so the template is not the only specification.
How can I help you explore Laravel packages today?