onelegstudios/shape
Shape offers a simple, expressive way to define and transform structured data in Laravel, so you can build consistent arrays, DTOs, and API payloads with less boilerplate and clearer intent. It helps keep validation, casting, and output formatting predictable across your app.
Architecture fit. Shape is a server-rendered Blade component library — anonymous Blade files, Tailwind utility classes, no compiled CSS, no JS build, no config publishing, no asset pipeline. That is the lowest-friction shape a Laravel UI dependency can take: it lives in the view layer, inherits Laravel's escaping and localization, and adds no runtime service-provider surface worth reasoning about. The deliberate split of variant (hierarchy) from tone (semantics) is a design-system decision encoded in the API rather than left to convention, which is precisely the thing that stops an application's UI from drifting into ad-hoc colour choices.
Overlays delegate to the platform: modal and drawer are <dialog>, dropdown/popover/tooltip use the popover attribute. Focus trap, top layer, Escape, light dismiss and scrim are the browser's problem, not the package's. What remains is one script file that imports nothing and depends on nothing — not Alpine, not Livewire. For a TPM that translates into a materially smaller failure surface and bundle than a JS-heavy component kit.
The Blaze story is the strategic bet. Annotations let the same component be folded into its parent at compile time, eliminating runtime component instantiation. It is optional at 0.1.0, and without it components render normally. That sequencing is correct: adopt the library, then adopt the optimiser on evidence.
Integration feasibility. composer require plus one artisan command is the whole install. Requirements are PHP 8.3–8.5 and Laravel 12–13, tested on Ubuntu and Windows across prefer-stable and prefer-lowest. Narrow but current; the practical consequence is that this cannot be evaluated on a Laravel 10/11 estate without an upgrade first. Livewire is not a dependency — Shape::toast() and Shape::confirm() dispatch through Livewire when there is a request to ride on and flash to session otherwise, arriving as the same event so one code path builds the toast either way. That is a genuinely good decision: the library can be piloted in a non-Livewire corner of the app without a second implementation.
Technical risk. Three items dominate.
First, 0.x with an explicit warning that component APIs may change before 1.0. Plan for churn; do not build a large surface against unstable props.
Second, the Blaze folding hazard. A folded component is pre-rendered while Blade compiles, so auth(), session(), config() or a translation inside one is resolved once and then served to everyone — a cross-user data-leak class of bug with no stack trace and no symptom in development. The package is unusually candid about this and ships shape:doctor, which exits non-zero and can sit in CI. That mitigation is the difference between "interesting risk" and "unacceptable risk" — but only if it is actually wired into CI, which is an operational commitment, not a package feature.
Third, the eject model. shape:eject copies a component and its dependency graph into the app, recording what the package held at copy time so shape:eject:status can distinguish your edits from upstream movement. Good tooling — but ejected components are now your code with your maintenance burden.
Key questions.
content glob for vendor/onelegstudios/shape/resources/views? "No build step" does not mean Tailwind can see classes it never scans.popover and <dialog>? Are fallbacks required for older Safari or older Chromium?shape:icon's upstream commit pinning create a supply-chain review obligation for the generated SVGs?Stack fit. Best fit is a Laravel 12/13 application already on Livewire and Tailwind, in active feature development rather than maintenance. There the library substitutes for months of design-system scaffolding at the cost of one composer constraint. Weaker fit for: multi-app estates on mixed Laravel versions, and teams already standardised on a competing kit (Flux, Filament, Mary UI) — the "zero specificity defaults" claim helps avoid !important wars but does not eliminate class collisions in an app whose palette is already Tailwind-derived. Note the aliasing design: Shape points at Tailwind's ramps rather than copying them, so retinting Tailwind retints Shape. Elegant, but it means Shape inherits your existing Tailwind colour decisions, including the ones you regret.
Migration path. Greenfield: adopt at project start, run shape:install, seed the brand through the optional stylesheet, done. Brownfield: do not attempt a wholesale swap. Pick one surface — typically a settings or admin area with forms, tables and a modal — and build it entirely in Shape. That single slice exercises forms, data display, overlays and feedback and gives a realistic read on the API before committing further.
Compatibility. Hard gates are PHP ≥ 8.3 and Laravel 12/13. Everything downstream — Livewire, Tailwind, Blaze — is soft. Blaze in particular should be a separate adoption decision with its own evaluation, made after the base library has proven itself in your codebase.
Sequencing.
shape:doctor to see the baseline output.shape:icon:all versus a named subset, and which set. Semi-irreversible, since regenerating shifts visuals at otherwise-unchanged call sites.shape:doctor into CI before any Blaze adoption, not after.Maintenance. Two distinct modes, and the team must know which applies to which component. Consumed components track the package: cheap, but 0.x means a minor bump can break call sites. Ejected components are forked code: you own them, and shape:eject:status tells you when upstream has moved underneath you but merges nothing for you. The tooling is drift detection, not drift resolution. Budget for periodic reconciliation and prefer consuming over ejecting unless you genuinely need to diverge.
Support. A pre-1.0 package from a single studio. Documentation is unusually strong — markdown in docs/, committed alongside the code, served in a workbench next to a gallery, with a test asserting every example still compiles. That last mechanism is the best available predictor of a maintainer who cares about correctness, and it materially reduces support burden because examples cannot rot silently. Still: no SLA, no vendor escalation path, bus factor of roughly one. Treat it as a community dependency with a built-in exit ramp (eject) rather than a supported product.
Scaling. Runtime cost is close to zero: no CSS build artefact, no JS bundle beyond one dependency-free file, no Alpine, no Livewire coupling for overlays. With Blaze, per-component render cost folds away entirely. Team scaling is the more interesting axis — the variant/tone split and the per-surface foreground contract give reviewers a vocabulary for rejecting UI PRs, which is what a design system is actually for. The shape:icon:replace --set= indirection means iconography can be restyled library-wide without touching a call site, valuable when brand direction shifts.
Failure modes, ranked by severity:
shape:doctor in CI, mandatory pre-Blaze, plus a code-review rule prohibiting auth()/session()/config()/__() inside components.popover/dialog on older targets.Ramp-up. Modest. A Laravel developer is productive on the components in a day. What takes longer is the design intent (variant vs tone, the foreground contract, seed derivation), the eject mental model, and — most importantly — why Blaze folding is dangerous when misused. That last one deserves a short mandatory read for anyone touching components, not a footnote. Estimate: half a day to a working pilot surface for one developer; one to two weeks before the team has settled conventions and the CI gate is live.
Recommendation. Worth a scoped pilot. The architecture suits a Laravel/Livewire/Tailwind stack, install cost is near zero, and the honest disclosure of the folding hazard plus a CI-checkable mitigation is a better signal than a promise the problem does not exist. Do not adopt Blaze during the pilot — adopt the components first, gate shape:doctor in CI, and treat 1.0 as the milestone for wider rollout.
How can I help you explore Laravel packages today?