anousss007/blatui
BlatUI brings shadcn/ui to the BLAT stack — Blade, Laravel, Alpine and Tailwind. A CLI copies 155 MIT-licensed, WCAG AA accessible components, 64 blocks and 70 charts straight into your project. You own the code, so edit freely. Livewire-ready, fully themeable, light and dark, no React.
Architecture fit. BlatUI is a source-distribution library, not a runtime dependency. The CLI copies Blade components into resources/views/components/ui/ and the theme/JS engine into resources/css and resources/js. That inverts the usual vendor-ownership model: after install, we own ~155 components and every line of their Alpine behavior. For a TPM this is the single most important property of the package. It buys unlimited customization, no vendor lock-in at runtime, no upgrade-forced-breaking-change treadmill, and trivially auditable markup — which matters if we have code-review, accessibility, or design-system governance requirements. It costs us the thing a vendor normally absorbs: patch delivery, security triage, and drift management.
The package is well-scoped for the Laravel/Blade idiom. Pure Blade + Alpine + Tailwind is the lowest-friction stack for a server-rendered Laravel app; there is no Node build step beyond Vite, no React island, no hydration story to reason about. The blatui:add dependency resolver (transitive component deps, plus printing required Composer/npm peers) and blatui:doctor (typeless buttons in forms, leaked tags) are the kind of affordances that signal the author has actually shipped this into apps rather than just authored a component gallery. The 1.24.1 changelog is a useful tell: a real CSS-vs-JS breakpoint bug, fixed with both a render test and a browser test that fails on the pre-fix component. That is a maintainer operating with a regression discipline.
Integration feasibility. Feasible in a day for a greenfield Laravel 11/12/13 app on Tailwind v4 + Alpine 3. The install path is explicit and the doc is unusually careful about the two genuine footguns: (1) double-booting Alpine by importing blatui.js when the app already runs Alpine, and (2) the Livewire/Flux case where Livewire owns Alpine and we must register via alpine:init and install plugins only. blatui:init as a doctor command gives a cheap, verifiable checkpoint before we write any UI.
The constraint that gates everything is Tailwind CSS v4. BlatUI relies on v4-only features (@theme inline, oklch tokens). Any existing app on Tailwind v3 must run npx @tailwindcss/upgrade first, and that migration is a project in its own right — it can restyle arbitrary existing pages and is not something we should bundle into "adopt a component library." Where we are on v4 already, or greenfield, integration cost collapses.
Technical risk.
| Risk | Severity | Assessment |
|---|---|---|
| License ambiguity | High (blocking, cheap to resolve) | GitHub reports NOASSERTION; README and Packagist both claim MIT. Resolve with legal before any commercial deployment. Do not treat as MIT on the strength of a badge. |
| Bus factor / adoption | High | 262 stars, 0 dependents, single-author monorepo. No downstream ecosystem means no community backpressure on bugs and no crowd-sourced fixes. |
| Security patching is ours | Medium-High | Copied source gets no CVE feed. An XSS or ARIA-handling flaw in an overlay component would be fixed upstream and we'd never be notified. We must own a subscription to upstream releases. |
| Update diffing is judgment-based | Medium | blatui:update cannot distinguish our customization from a stale copy, so it prompts file-by-file. Safe by design, but it means upgrades are a real work item, not composer update. |
| Formatter churn | Medium | Pint/Prettier over resources/views makes every copied component read as "changed"; mitigated by --ignore-whitespace, but only if the team knows to use it. |
| Blocks/charts are fetched over HTTP | Medium | 64 blocks and 70 charts are not in the package — they are pulled from blatui.remix-it.com/r/...json. Third-party availability and content-integrity dependency, and an air-gap blocker for regulated environments. |
| Livewire/Flux coexistence | Low-Medium | Documented (darkMode: false to avoid two .dark togglers), but it is a real conflict class with Flux Pro, which is the incumbent we'd be displacing. |
| Release cadence | Low | 1.28.x with dense point releases implies an active but fast-moving surface; pin the Composer constraint and treat upstream diffs as opt-in. |
| Accessibility claims | Low-Medium | WCAG AA and axe-core auditing are asserted by the vendor. AA conformance of our pages is our legal exposure, not theirs; we must re-verify in our own context. |
Key questions for the maintainer / for us.
NOASSERTION)?/r/blocks/*, /r/charts/*) versioned and immutable, or does fetching the same URL a month apart yield different code?blatui:mcp server have any write path beyond reading the registry and invoking blatui:add? What should we restrict in agent-driven environments?Stack fit. BlatUI targets exactly one stack and does so honestly: PHP 8.2+, Laravel 11/12/13, Tailwind v4, Alpine 3, Node 18+. Peer packages are small and uncontroversial — gehrisandro/tailwind-merge-laravel for class conflict resolution and mallardduck/blade-lucide-icons for icons. Charts add apexcharts (lazy-loaded by the engine), which we can drop if we don't need 70 chart variants. No PHP runtime coupling beyond the service provider; no middleware, no DB, no queue. Blast radius on the backend is effectively zero.
Migration path. Three distinct entry points, each with different cost:
blatui:init, then blatui:add per feature. This is the cheap path and the one I'd recommend as the pilot.@import "./blatui.css" below the Tailwind import, and register via registerBlatUI(Alpine) from blatui-core.js before Alpine.start() — never import blatui.js. Low risk, mechanical.alpinejs), register inside the alpine:init hook, and pass { darkMode: false } if Flux already drives dark mode. Correct but easy to get wrong; this is the configuration that needs a documented internal runbook and a code-review checklist item, because the failure mode (silent double-Alpine) is confusing to debug.Compatibility. Compatibility is mostly the peer-dependency graph plus Vite. The realistic compatibility watch-list is: Tailwind major version, Alpine major version, Livewire's bundled Alpine, and Flux's dark-mode ownership. Everything else is inert. Worth an explicit note that the package is a monorepo where stubs/ is generated from apps/demo/ and CI enforces no drift — which means the published artifacts and the demo site cannot silently diverge, a genuinely good sign for a copy-paste library.
Sequencing. Staged, with explicit exit criteria:
blatui:update --dry-run --diff --ignore-whitespace to a recurring calendar item.blatui:init green, install 8–12 components covering form, overlay, and data-table patterns. Exit criteria: blatui:doctor clean, axe-core clean on two real pages, one form control verified against wire:model.blatui.css tokens before breadth, because tokens are the cheap global lever and per-component edits are not. Publish an internal rule: token edits yes, component-fork edits require review (they are what makes future updates expensive).blatui:add per feature rather than --all — --all maximizes the eventual diff-review surface for zero near-term benefit.Maintenance. This is the dominant cost and it should be budgeted explicitly, not discovered. We own the copied source: no automated security patches, no forced upgrades, and no vendor telling us something broke. In exchange, nothing breaks without our consent. Practically that means (a) a named owner for upstream release review, (b) an update cadence tied to releases we care about rather than every 1.28.x bump, and (c) a discipline of token-level customization over component-level forks, because forks convert every future update into manual conflict resolution. The .bak / --force / --dry-run / --ignore-whitespace tooling is genuinely thoughtful here — it treats "we can't tell your edit from a stale copy" as an honest problem rather than papering over it — but it only helps teams that use it deliberately.
Realistically: expect ~2–4 hours per update cycle for a mid-size surface with light customization, and materially more if the team has forked components. Treat that as a recurring line item.
Support. There is no commercial support. Support is the maintainer's GitHub issue tracker plus the docs site, and with 0 dependents there is no community to fall back on. Two mitigations: (1) because we own the source, worst case we fix it ourselves — this is the real safety net and it is a strong one for UI code; (2) keep our forks minimal so a self-fix is a small patch, not a rewrite. Internal support load concentrates on two areas: Alpine/Livewire bootstrap wiring (well-documented, so a one-page runbook solves it) and the update-diff workflow (process, not technology).
Scaling. Two axes. Team scaling is favorable: Blade components with a stable x-ui.* API are easy to onboard onto, and the component-per-file structure means parallel work doesn't collide. The hazard is uncontrolled forking — twenty engineers, twenty slightly different button.blade.php variants. Enforce the token/component boundary in review. Application scaling is unaffected: these are server-rendered views, no client-side component runtime, no bundle-size catastrophe. The only runtime cost is ApexCharts (lazy-loaded, drop it if unused) and the Alpine plugins. Accessibility at scale is the item to instrument — put axe-core in CI so AA is a gate rather than a claim.
Failure modes. Ranked by likelihood × impact:
blatui.js alongside an existing Alpine/Livewire app. Mitigate with the runbook and a review checklist item.@theme mapping don't resolve; components render unstyled. blatui:init catches this early; the trap is skipping the doctor.theme store and Flux both flip .dark, producing theme flicker or stuck state. Fixed by { darkMode: false }; invisible until someone tests a theme toggle.--ignore-whitespace in the update runbook.--dry-run --diff sweep, monthly at minimum.Ramp-up. Low, and front-loaded. A Laravel developer productive in Blade is productive with x-ui.* in under a day — the component APIs are deliberately shadcn-shaped, so prior shadcn/ui exposure transfers directly and even prior-less developers get readable markup. The learning curve is not component usage; it is the operational envelope: Alpine ownership in our specific app, the published-foundations model (edit tokens, re-sync with vendor:publish --force, run blatui:init), and the update workflow. Budget one focused session for the team lead on those three, then a written runbook. The skills/blatui-development/SKILL.md agent skill is a genuine accelerant for AI-assisted development — but it also means agents can pull component code (and registry content) into the repo autonomously, which needs a governance answer if blatui:mcp is enabled anywhere.
Verdict from a delivery standpoint: strong technical fit for Laravel/Blade on Tailwind v4, unusually honest tooling, and a favorable ownership model for UI specifically. The two things standing between "evaluate" and "adopt" are not technical — they are the unresolved license and the absence of any adoption signal behind a 262-star, single-maintainer project. Resolve the license, run the two-week pilot, and the decision makes itself on evidence.
How can I help you explore Laravel packages today?