satoved/laravel-livewire-steps
Lightweight Livewire component for building wizards (multi-step forms). Each step is a Livewire 3 form object, while a single WizardComponent handles navigation. Extend WizardComponent, list your steps as public properties, and render the current step with minimal code.
Architecture fit
The package is two base classes — WizardComponent and StepForm — and nothing else. There is no config file, no service provider surface to configure, no migration, no asset pipeline, no published views. That means it is not a framework you adopt; it is an inheritance seam you subclass. Fit is therefore narrow and easy to test: it works if the application is already Livewire 3+ centric and the flows are linear, server-validated, and completed in one sitting. It does not fit branching flows, multi-day resumable journeys, or wizards whose steps trigger external side effects (payments, provisioning, KYC submission), because the package gives you a step cursor and per-step validation and stops there.
The one defensible architectural advantage is request economy. Because a step is a form object rather than a nested Livewire component, a transition costs one Livewire round trip instead of two (the explicit motivation for the package versus spatie/laravel-livewire-wizard). At 3–6 steps that is a latency nicety, not a decision driver. Treat it as a tiebreaker, not a reason to adopt.
Integration feasibility
High, and cheap to prove. composer require satoved/laravel-livewire-steps, one public property per step in declaration order, one render() per step. A TPM can fund a one-day spike: read src/Livewire/WizardComponent.php and src/Livewire/Forms/StepForm.php, then clone the companion laravel-livewire-steps-demo repo. That is the entire onboarding surface — the two files are the only authoritative documentation for anything the README omits, and the README is thin enough that this is not an exaggeration.
Technical risk The dominant risk is not code quality; it is project gravity. 6 stars, 0 dependents, a single maintainer plus one outside contributor, and a release history that consists almost entirely of framework compatibility bumps (Livewire 4 support in v1.3.0, Laravel 13 in v1.4.0). That last point is double-edged: it shows the maintainer tracks framework churn promptly, which is the maintenance burden that actually matters, but it also means the package's continued existence is one person's attention span.
| Risk | Severity | Notes |
|---|---|---|
| Bus factor / abandonment | Medium | MIT license, ~2 files of real surface — forking is genuinely cheap. The risk is organizational delay, not technical impossibility. |
| Undocumented API surface | Medium | Skip-step shipped in v1.1.0 and never reached the README. The real navigation contract lives in source, not docs. |
| Positional step semantics | Medium | Flow order is public property declaration order. Reordering is a silent breaking change in your app; step indices are not stable identifiers. |
| No cross-step validation | Medium | #[Validate] on step properties covers one step. Password confirmation, date ordering, uniqueness checks, and re-validating prior steps before finish are all application work. |
| No persistence | Medium | State rides in Livewire's component snapshot; a hard refresh restarts at step one. |
| No UI layer | Low | No progress bar, no back button, no step labels. All yours to build. |
| Stale-validation hole | High | Navigate forward, go back, edit to invalid, advance — the classic bug is only the final step's rules running. Cheap to fix, expensive to discover in production. |
Key questions to resolve in the spike
nextStep() no-op or throw on validation failure, and are errors keyed to the wizard-qualified path (emailStep.email) so @error blocks work without translation?skipStep() signature and semantics — does it bypass validation, advance the cursor, emit anything?StepForm instances reusable across wizards without state bleed between component instances?Stack fit Laravel with Livewire 3.x or 4.x per the changelog; Laravel 13 explicitly supported. Composer-only, no front-end opinion — it composes cleanly with Tailwind and your existing Blade component library, and adds no JavaScript beyond what Livewire already ships. This is a low-ceremony dependency by design, which is the correct thing to optimize for when you're buying 150 lines of step-sequencing logic.
Migration paths
StepForm, move validation onto #[Validate] attributes, delete bespoke session/index logic. Mechanical and low-risk; size at roughly one wizard per sprint-day including tests.spatie/laravel-livewire-wizard: not a drop-in. Spatie steps are Livewire components; here they are form objects. Every step view needs wire:model paths requalified to the wizard property (emailStep.email), every @error key updated, and every per-step component class dissolved into a render() on the form object. Budget 0.5–1 dev-day per existing wizard plus regression testing, and do not migrate a wizard with side effects until the wrapper base class is in place.Compatibility and versioning
Pin to a caret minor (^1.4) and record the exact resolved version in a short dependency ADR. Because there is no config or migration surface, upgrades are cheap — but the public API is inherited methods, so a minor bump can change transition semantics without a deprecation. That ADR is what lets a future maintainer upgrade confidently.
Sequencing
app/Livewire/Wizards/BaseWizard extending WizardComponent, carrying: derived progress/labels, a revalidate-all-steps pass before the finish handler, transition events for analytics, and optional persistence hooks. Every wizard in the codebase extends this, never WizardComponent directly. This single file is your exit ramp.Explicitly out of scope for the pilot: checkout, payments, KYC, anything where a lost step has a financial or compliance consequence.
Maintenance
Low volume, concentrated in one place. No config to drift, no migrations to run, no scheduled work, no published assets to rebase. Real maintenance is two things: framework compatibility bumps, and the slow accumulation of behavior in BaseWizard that makes it a de facto fork. Name a single owner at adoption time and write the fork-and-pin policy before the second wizard ships — the MIT license makes the decision free, but only if you make it early. Waiting until eight wizards depend on the package turns a five-minute decision into a two-week one.
Support Community-only. GitHub issues, no SLA, no vendor, no security response capacity beyond a policy file. Acceptable for non-revenue paths; not acceptable for anything where a broken step blocks a transaction. If a wizard lands in a purchase flow, the plan must assume internal ownership of the two source files — which is realistic, because it's two files.
Scaling
Failure modes and mitigations
| Failure | Symptom | Mitigation |
|---|---|---|
| Validation failure with no visible error | nextStep appears to do nothing |
Error block + wire:loading on every step template; make it a PR checklist item |
| Hard refresh | Wizard restarts at step 1 | Persistence layer, or an explicit accepted-behavior decision recorded in the ADR |
| Back → edit → forward | Stale/invalid prior-step data submitted | Revalidate-all in the wrapper's finish path |
| Step inserted or reordered | Persisted "step 2" now means something else | Never persist integer indices; persist a stable step key |
| Livewire major bump | Base classes break at transition boundaries | Pinned fork, upgrade in a branch, transition smoke tests in CI |
| Maintainer abandonment | No upstream fixes | MIT fork exists; cost of takeover is low, so the risk is schedule delay, not capability loss |
Ramp-up
A competent Livewire developer is productive in half a day and fluent in two. The package itself is not the learning curve — the two conventions and the stale-validation hole are. Budget onboarding time against BaseWizard, not against the package README, and point new hires at the demo repo first.
Recommendation Adopt for linear, low-to-medium-stakes multi-step forms, with the wrapper base class and a pinned version in place from day one. Do not adopt for branching flows, resumable journeys, or revenue-critical paths without accepting internal ownership of the source. The overall score is low because adoption is low, not because the design is wrong — the design is a good, small answer to a narrow problem, and the exit cost is roughly one day of engineering. That asymmetry is what makes it a reasonable bet.
How can I help you explore Laravel packages today?