PHPackages                             pixelworxio/livewire-workflows - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. pixelworxio/livewire-workflows

ActiveLibrary[Framework](/categories/framework)

pixelworxio/livewire-workflows
==============================

Build multi-step workflows in Laravel / Livewire with zero boilerplate

0.5.5b(2mo ago)8022↓50%5[1 PRs](https://github.com/pixelworxio/livewire-workflows/pulls)MITPHPPHP ^8.3CI passing

Since Nov 4Pushed 1mo ago2 watchersCompare

[ Source](https://github.com/pixelworxio/livewire-workflows)[ Packagist](https://packagist.org/packages/pixelworxio/livewire-workflows)[ Docs](https://github.com/pixelworxio/livewire-workflows)[ GitHub Sponsors](https://github.com/Pixelworxio)[ RSS](/packages/pixelworxio-livewire-workflows/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (16)Versions (13)Used By (0)

[![Livewire Workflows Banner](https://raw.githubusercontent.com/pixelworxio/livewire-workflows/main/resources/livewire-workflows-banner.png)](https://raw.githubusercontent.com/pixelworxio/livewire-workflows/main/resources/livewire-workflows-banner.png)

 [![GitHub Tests Action Status](https://camo.githubusercontent.com/d6bb32bcc65c81023dd1a34ca9700eee6c626f5de74f32699f727f6050c87386/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f706978656c776f7278696f2f6c697665776972652d776f726b666c6f77732f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/pixelworxio/livewire-workflows/actions/workflows/run-tests.yml) [![GitHub Stars](https://camo.githubusercontent.com/c16a7171b542e42741339fa017c7b2429bf8f45c65c7f0801e0f070f13fba6d1/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f706978656c776f7278696f2f6c697665776972652d776f726b666c6f77733f7374796c653d666c61742d737175617265)](https://github.com/pixelworxio/livewire-workflows)

---

Livewire Workflows (BETA)
=========================

[](#livewire-workflows-beta)

**Build powerful multi-step workflows in Laravel with zero boilerplate.** Define complex user journeys—onboarding, checkouts, surveys—using an expressive, route-like DSL. Get automatic route registration, guard-based navigation, state persistence, and full Livewire 4.x integration out of the box. Livewire 3.x is also supported.

```
// Define a complete workflow in seconds
Workflow::flow('onboarding')
    ->entersAt(name: 'onboarding.start', path: '/onboarding')
    ->finishesAt('dashboard')
    ->step('verify-email')
        ->goTo(VerifyEmail::class)
        ->unlessPasses(EmailVerifiedGuard::class)
        ->order(10)
    ->step('profile')
        ->goTo(EditProfile::class)
        ->unlessPasses(ProfileCompletedGuard::class)
        ->order(20);
```

That's it. No manual routes. No state management headaches.

View the testbench repo, , for examples of how this package can help you with your project.

---

✨ Why Livewire Workflows?
-------------------------

[](#-why-livewire-workflows)

FeatureLivewire WorkflowsManual Implementation**Route Management**✅ Auto-generated❌ Define every route manually**State Persistence**✅ Built-in (Session/DB)❌ Roll your own**Navigation Logic**✅ Guard-based pipeline❌ Complex conditionals everywhere**Back Button**✅ History tracking❌ Custom session juggling**Progress Tracking**✅ One method call❌ Calculate yourself**Events &amp; Analytics**✅ Fire automatically❌ Remember to dispatch**Result:** Spend time building features, not workflow infrastructure.

---

📦 Installation
--------------

[](#-installation)

```
composer require pixelworxio/livewire-workflows
```

### Quick Setup (Session-Based)

[](#quick-setup-session-based)

```
php artisan workflows:install
```

### Production Setup (Database-Backed)

[](#production-setup-database-backed)

```
php artisan workflows:install --with-db
php artisan migrate
```

---

🚀 Quick Start (3 Minutes)
-------------------------

[](#-quick-start-3-minutes)

### 1. Define Your Workflow

[](#1-define-your-workflow)

Open `routes/workflows.php`:

```
use Pixelworxio\LivewireWorkflows\Facades\Workflow;

Workflow::flow('onboarding')
    ->entersAt(name: 'onboarding.start', path: '/onboarding')
    ->finishesAt('dashboard')
    ->step('verify-email')
        ->goTo(\App\Livewire\Onboarding\VerifyEmail::class)
        ->unlessPasses(\App\Guards\EmailVerifiedGuard::class)
        ->order(10)
    ->step('profile')
        ->goTo(\App\Livewire\Onboarding\EditProfile::class)
        ->unlessPasses(\App\Guards\ProfileCompletedGuard::class)
        ->order(20);
```

**Routes auto-registered:**

- Entry: `GET /onboarding` → `onboarding.start`
- Step 1: `GET /onboarding/verify-email` → `onboarding.verify-email`
- Step 2: `GET /onboarding/profile` → `onboarding.profile`

### 2. Create a Guard

[](#2-create-a-guard)

**Quick Generation:**

```
php artisan make:workflow-guard EmailVerified
```

This generates a guard at `App\Guards\EmailVerifiedGuard.php` with the proper structure.

```
namespace App\Guards;

use Illuminate\Http\Request;
use Pixelworxio\LivewireWorkflows\Contracts\GuardContract;

class EmailVerifiedGuard implements GuardContract
{
    public function passes(Request $request): bool
    {
        return true;
    }

    public function onEnter(Request $request): void {}
    public function onExit(Request $request): void {}
    public function onPass(Request $request): void {}
    public function onFail(Request $request): void {}
}
```

**Guard Logic:** `passes() = true` → skip step. `passes() = false` → show step.

### 3. Build Your Livewire Component

[](#3-build-your-livewire-component)

```
namespace App\Livewire\Onboarding;

use Livewire\Component;
use Pixelworxio\LivewireWorkflows\Attributes\WorkflowStep;
use Pixelworxio\LivewireWorkflows\Livewire\Concerns\InteractsWithWorkflows;

#[WorkflowStep(flow:'onboarding', key:'verify-email')]
class VerifyEmail extends Component
{
    use InteractsWithWorkflows;

    public function resend()
    {
        auth()->user()->sendEmailVerificationNotification();
        session()->flash('message', 'Verification email sent!');
    }

    public function goToNextStep(): void
    {
        // ... handle your logic

        $this->continue('onboarding'); // workflow name is optional when using WorkflowStep attribute
    }

    public function render()
    {
        return view('livewire.onboarding.verify-email');
    }
}
```

**And in your Blade view:**

```

    Verify Your Email
    Check your inbox for the verification link.

    Resend Email

        I've Verified — Continue

```

### 4. Done!

[](#4-done)

Visit `/onboarding`. The package:

1. Evaluates guards in order
2. Redirects to first incomplete step
3. Tracks progress automatically
4. Completes when all steps pass

---

📖 Core Concepts
---------------

[](#-core-concepts)

### Auto-Generated Routes

[](#auto-generated-routes)

Routes are **automatically registered** from your DSL:

```
->entersAt(name: 'checkout.start', path: '/checkout')  // Entry route
->step('shipping')                                       // Auto: /checkout/shipping
->step('payment')                                        // Auto: /checkout/payment
```

**Generated:**

- `checkout.start` → `/checkout`
- `checkout.shipping` → `/checkout/shipping`
- `checkout.payment` → `/checkout/payment`

### Dynamic Routes with Parameters

[](#dynamic-routes-with-parameters)

Workflows support **dynamic route parameters** and **route model binding**:

```
Workflow::flow('user-checkout')
    ->entersAt(name: 'user-checkout.start', path: '/user/{user}/checkout/{product}')
    ->finishesAt('dashboard')
    ->step('shipping')
        ->goTo(\App\Livewire\Checkout\Shipping::class)
        ->unlessPasses(\App\Guards\HasShippingAddress::class)
        ->order(10)
    ->step('payment')
        ->goTo(\App\Livewire\Checkout\Payment::class)
        ->unlessPasses(\App\Guards\HasPaymentMethod::class)
        ->order(20);
```

**Generated Routes:**

- `user-checkout.start` → `/user/{user}/checkout/{product}`
- `user-checkout.shipping` → `/user/{user}/checkout/{product}/shipping`
- `user-checkout.payment` → `/user/{user}/checkout/{product}/payment`

**Route Model Binding:**

```
// Supports Laravel's route model binding syntax
->entersAt(name: 'checkout.start', path: '/user/{user:id}/product/{product:slug}')
```

**Navigation Preserves Parameters:**

Route parameters are automatically passed through all workflow navigation:

```
class Shipping extends Component
{
    use InteractsWithWorkflows;

    protected ?string $workflowName = 'user-checkout';

    // Livewire receives route parameters
    public function mount($user, $product)
    {
        // $user and $product are automatically injected
    }

    public function submit()
    {
        // Parameters are automatically preserved when continuing
        $this->continue($this->workflowName); // Still navigates with {user} and {product}
    }
}
```

The `continue()` and `back()` methods automatically extract and pass route parameters from the current request, ensuring seamless navigation throughout the workflow.

### Guard Behavior

[](#guard-behavior)

Guards use **positive semantics**:

```
class ProfileCompleteGuard implements GuardContract
{
    public function passes(Request $request): bool
    {
        return $request->user()->profile_completed;
    }
}
```

Guard ResultStep Behavior`passes() = true`**Skip** this step`passes() = false`**Show** this stepUse `unlessPasses(Guard::class)`: "Show step UNLESS guard passes."

### Navigation Flow

[](#navigation-flow)

1. User visits entry route (`/onboarding`)
2. Package evaluates guards in `order`
3. Redirects to first failing guard's step
4. User completes step, calls `$this->continue('onboarding')`
5. Re-evaluates from entry → next unmet step or finish

---

🧩 Advanced Features
-------------------

[](#-advanced-features)

### State Management

[](#state-management)

#### Setting Workflow Name

[](#setting-workflow-name)

Use the `#[WorkflowName]` attribute to explicitly declare your component's workflow, when not using the WorkflowStep attribute:

```
use Pixelworxio\LivewireWorkflows\Attributes\WorkflowName;

#[WorkflowName('checkout')]
class CheckoutShipping extends Component
{
    use InteractsWithWorkflows;

    // protected ?string $workflowName = 'checkout'; // No need to set
}
```

**Benefits:**

- ✅ Eliminates boilerplate
- ✅ Makes workflow association explicit
- ✅ Auto-detected during component boot
- ✅ Falls back to route-based detection if not present

#### Persisting State

[](#persisting-state)

Persist data across workflow steps with the `#[WorkflowState]` attribute:

```
use Pixelworxio\LivewireWorkflows\Attributes\WorkflowName;
use Pixelworxio\LivewireWorkflows\Attributes\WorkflowState;

#[WorkflowName('checkout')]
class CheckoutShipping extends Component
{
    use InteractsWithWorkflows;

    #[WorkflowState]
    public ?string $address = null;

    #[WorkflowState(encrypt: true)]
    public ?string $creditCard = null;

    #[WorkflowState(namespace: 'shipping')]
    public ?string $method = null;
}
```

**Features:**

- Auto-hydration on mount
- Auto-persistence on dehydrate
- Encryption support
- Namespace grouping
- Session or database storage

[Full state management guide →](STATE_MANAGEMENT.md)

### Progress Tracking

[](#progress-tracking)

```
$progress = workflow('onboarding')->progressFor($request);

// Returns:
[
    'total' => 3,
    'completed' => 1,
    'remaining' => 2,
    'percentage' => 33.33,
    'current_step' => 'verify-email',
    'next_step' => 'profile',
    'is_complete' => false,
]
```

### Events

[](#events)

Listen to workflow lifecycle:

```
use Pixelworxio\LivewireWorkflows\Events\{WorkflowAdvanced, WorkflowCompleted};

Event::listen(WorkflowAdvanced::class, function ($event) {
    Log::info("User {$event->userKey} moved from {$event->fromKey} to {$event->toKey}");
});

Event::listen(WorkflowCompleted::class, function ($event) {
    Mail::to($user)->send(new OnboardingComplete());
});
```

### CLI Tools

[](#cli-tools)

```
# Generate a new workflow
php artisan make:workflow checkout

# Generate a guard class
php artisan make:workflow-guard EmailVerified

# Add a step to existing workflow
php artisan make:workflow-step checkout payment \
    --component=App\\Livewire\\Checkout\\Payment \
    --guard=App\\Guards\\CartNotEmptyGuard \
    --order=20

# Validate and document all workflows
php artisan workflows:scan
```

---

🎯 Real-World Examples
---------------------

[](#-real-world-examples)

### Multi-Page Checkout

[](#multi-page-checkout)

```
Workflow::flow('checkout')
    ->entersAt(name: 'checkout.start', path: '/checkout')
    ->finishesAt('orders.confirmation')
    ->step('cart')
        ->goTo(ReviewCart::class)
        ->unlessPasses(CartNotEmptyGuard::class)
        ->order(10)
    ->step('shipping')
        ->goTo(ShippingAddress::class)
        ->unlessPasses(ShippingAddressGuard::class)
        ->order(20)
    ->step('payment')
        ->goTo(PaymentMethod::class)
        ->unlessPasses(PaymentMethodGuard::class)
        ->order(30);
```

### Employee Onboarding

[](#employee-onboarding)

```
Workflow::flow('employee-onboarding')
    ->entersAt(name: 'onboard.start', path: '/onboard')
    ->finishesAt('employee.dashboard')
    ->step('paperwork')
        ->goTo(Paperwork::class)
        ->unlessPasses(PaperworkCompleteGuard::class)
        ->order(10)
    ->step('it-setup')
        ->goTo(ITSetup::class)
        ->unlessPasses(ITAccountGuard::class)
        ->order(20)
    ->step('training')
        ->goTo(TrainingModules::class)
        ->unlessPasses(TrainingCompleteGuard::class)
        ->order(30);
```

### User Registration Flow

[](#user-registration-flow)

```
Workflow::flow('signup')
    ->entersAt(name: 'signup.start', path: '/signup')
    ->finishesAt('welcome')
    ->step('account')
        ->goTo(CreateAccount::class)
        ->unlessPasses(AccountCreatedGuard::class)
        ->order(10)
    ->step('verify-email')
        ->goTo(VerifyEmail::class)
        ->unlessPasses(EmailVerifiedGuard::class)
        ->order(20)
    ->step('preferences')
        ->goTo(SetPreferences::class)
        ->unlessPasses(PreferencesSetGuard::class)
        ->order(30);
```

---

🔧 Configuration
---------------

[](#-configuration)

Publish and customize the config:

```
php artisan vendor:publish --tag=livewire-workflows-config
```

**`config/livewire-workflows.php`:**

```
return [
    // State persistence: 'null', 'session', or 'eloquent'
    'repository' => env('WORKFLOWS_REPOSITORY', 'session'),

    // Middleware applied to all workflow routes
    'middleware' => ['web', 'auth'],
];
```

### State Repository Options

[](#state-repository-options)

RepositoryUse CasePersistence`null`Stateless workflowsNone`session`Guest users, simple flowsSession lifetime`eloquent`Authenticated users, productionDatabase---

📊 API Reference
---------------

[](#-api-reference)

### Workflow DSL

[](#workflow-dsl)

```
Workflow::flow(string $name)
    ->entersAt(name: string, path: string)
    ->finishesAt(string $routeName)
    ->step(string $key)
        ->goTo(string $componentClass)
        ->unlessPasses(string $guardClass)
        ->order(int $order);
```

### Livewire Trait Methods

[](#livewire-trait-methods)

```
use InteractsWithWorkflows;

$this->continue(string $flow): RedirectResponse
$this->back(string $flow, string $currentKey): ?RedirectResponse
$this->syncState(): void  // Manually persist state
```

Note: When using the `#[WorkflowStep]` attribute, the `$flow` and `$currentKey` properties are optional

```
#[WorkflowStep(flow: 'my-flow', key: 'current-step', middleware: ['auth'])]

use InteractsWithWorkflows;

$this->continue(): RedirectResponse
$this->back(): ?RedirectResponse

```

### Helper Functions

[](#helper-functions)

```
workflow(string $flow)->redirect(Request $request, ?string $doneRoute = null)
workflow(string $flow)->nextRouteNameFor(Request $request, ?string $doneRoute = null)
workflow(string $flow)->previousRouteNameFor(string $currentKey, Request $request)
workflow(string $flow)->progressFor(Request $request)
```

### State Management Helpers

[](#state-management-helpers)

```
// Automatic with attributes
#[WorkflowState] public ?string $email = null;
#[WorkflowState(encrypt: true)] public ?string $password = null;
#[WorkflowState(namespace: 'profile')] public ?string $name = null;

// Manual helpers
$this->putWorkflowState(string $key, mixed $value)
$this->getWorkflowState(string $key, mixed $default = null)
$this->hasWorkflowState(string $key)
$this->forgetWorkflowState(string $key)
$this->clearWorkflowState(?string $namespace = null)
$this->allWorkflowState()
```

---

🆚 Comparison with Alternatives
------------------------------

[](#-comparison-with-alternatives)

\*\*Or so Claude.ai says...

FeatureLivewire WorkflowsSpatie Laravel WizardCustom SolutionRoute Auto-Registration✅❌❌Guard-Based Navigation✅❌CustomState Persistence✅ Built-in❌CustomLivewire 4 &amp; 3 Native✅⚠️ LimitedN/AHistory/Back Support✅⚠️ BasicCustomProgress Tracking✅❌CustomEvents✅❌CustomLearning CurveLowMediumHigh---

💬 FAQ
-----

[](#-faq)

**Does this support Livewire v4?**Yes. The package is built and certified for Livewire v4, with full backward compatibility for Livewire v3. All lifecycle hooks and the redirect/navigation API are identical across both versions.

**Do I need to define routes manually?**No. Step routes are auto-registered from your DSL. You only need to define the finish route in your regular `routes/web.php`, if not already present.

**Can I protect workflows with authentication?**Yes. Add `'auth'` to the `middleware` array in `config/livewire-workflows.php`.

**How do I skip steps dynamically?**Make the guard's `passes()` method return `true` when the step should be skipped.

**Can workflows share state?**No. State is scoped per workflow and per user. This is by design for data isolation.

**What happens if a user jumps to a step URL directly?**The step page loads, but calling `continue()` will re-evaluate guards and redirect appropriately.

---

🛠️ Requirements
---------------

[](#️-requirements)

- PHP 8.3+
- Laravel 11.x or 12.x
- Livewire 4.x (3.x also supported)

---

🤝 Contributing
--------------

[](#-contributing)

Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.

### Development Setup

[](#development-setup)

```
git clone https://github.com/pixelworxio/livewire-workflows.git
cd livewire-workflows
composer install
composer test
```

---

📜 License
---------

[](#-license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

---

🙏 Credits
---------

[](#-credits)

- [Whoisthisstud](https://github.com/whoisthisstud)

Built with ❤️ using [Laravel](https://laravel.com), [Livewire](https://livewire.laravel.com), and [Spatie's Package Tools](https://github.com/spatie/laravel-package-tools).

---

🌟 Show Your Support
-------------------

[](#-show-your-support)

Give a ⭐️ if this project helped you!

 [ ![GitHub Stars](https://camo.githubusercontent.com/080707b28460daa54f1ec2236bc3a911bd359753e55363d487b5847037048d7b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f706978656c776f7278696f2f6c697665776972652d776f726b666c6f77733f7374796c653d736f6369616c) ](https://github.com/pixelworxio/livewire-workflows) [ ![Tweet](https://camo.githubusercontent.com/3102b004745103bf939bfda91985d35f11e08fe7949f0e0346ed6bff8173062b/68747470733a2f2f696d672e736869656c64732e696f2f747769747465722f75726c3f7374796c653d736f6369616c2675726c3d68747470732533412532462532466769746875622e636f6d253246706978656c776f7278696f2532466c697665776972652d776f726b666c6f7773) ](https://twitter.com/intent/tweet?text=Check%20out%20Livewire%20Workflows%20for%20Laravel!&url=https://github.com/pixelworxio/livewire-workflows)

###  Health Score

45

—

FairBetter than 92% of packages

Maintenance87

Actively maintained with recent releases

Popularity22

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 80.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~11 days

Recently: every ~22 days

Total

10

Last Release

81d ago

PHP version history (2 changes)0.1aPHP ^8.4

0.3aPHP ^8.3

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/195972705?v=4)[Pixelworx](/maintainers/Pixelworxio)[@pixelworxio](https://github.com/pixelworxio)

---

Top Contributors

[![whoisthisstud](https://avatars.githubusercontent.com/u/44807533?v=4)](https://github.com/whoisthisstud "whoisthisstud (82 commits)")[![claude](https://avatars.githubusercontent.com/u/81847?v=4)](https://github.com/claude "claude (16 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (3 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

laravellivewirelivewire-laravellivewire-packageslivewire3multi-stepmulti-step-formphpworkflowworkflowslaravelworkflowlivewireFormsmultistep

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/pixelworxio-livewire-workflows/health.svg)

```
[![Health](https://phpackages.com/badges/pixelworxio-livewire-workflows/health.svg)](https://phpackages.com/packages/pixelworxio-livewire-workflows)
```

###  Alternatives

[laravel/pulse

Laravel Pulse is a real-time application performance monitoring tool and dashboard for your Laravel application.

1.7k12.1M99](/packages/laravel-pulse)[laravel/folio

Page based routing for Laravel.

608453.9k27](/packages/laravel-folio)[spatie/laravel-livewire-wizard

Build wizards using Livewire

4061.0M4](/packages/spatie-laravel-livewire-wizard)[spatie/livewire-filepond

Upload files using Filepond in Livewire components

306452.7k3](/packages/spatie-livewire-filepond)[tomshaw/electricgrid

A feature-rich Livewire package designed for projects that require dynamic, interactive data tables.

116.6k](/packages/tomshaw-electricgrid)[mwguerra/web-terminal

A web-based terminal component for Filament/Laravel with command whitelisting and multiple connection types

251.1k](/packages/mwguerra-web-terminal)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
