Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Flow Laravel Package

packstub/filament-flow

Filament Flow is a Laravel Filament package for defining and managing multi-step workflows directly in your admin panel. Build, visualize, and track flows for approvals, pipelines, and status-driven records in a clean, integrated UI.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire it up in the time-honoured Filament plugin order:

composer require packstub/filament-flow
php artisan vendor:publish --tag="packstub-flow-config"
php artisan vendor:publish --tag="packstub-flow-migrations"   # or copy the stub manually
php artisan migrate
php artisan filament:assets

Then register the plugin on the panel you want the automation surface to live in (in a PanelProvider's ->plugins([...])), and make sure you have at least one supervised queue worker — not because runs must be queued, but because Wait steps always are, and a panel with a dead worker will look fine right up until the first delayed step silently never fires.

Where to look first, in this order:

  1. docs/ — customer-facing docs with screenshots; the fastest way to see the intended authoring UX.
  2. config/packstub-flow.php — queue connection, node registration, access control, styling. This is the file you will actually edit.
  3. src/Nodes/ — the Trigger / Action / Condition base classes plus the built-ins. This is the extension seam you will spend your life in.
  4. src/Engine/ — Dispatcher, Graph, Runner. Read these before you debug anything that "didn't run".
  5. resources/lang/en/flow.php — every UI string, node name, and description in one file. Publish or override it rather than fighting copy in the canvas.

First use case: pick a read-only automation with zero write-back risk — a lead-routing workflow that fires on record creation and sends a notification. You get the full loop (trigger → condition → action → run history) without betting any production data on a 20-star package. Once that runs cleanly for a business cycle, add a Wait step and deliberately kill the worker mid-run, so you learn the failure shape on your terms rather than at 2am.

Implementation Patterns

Author in the UI, extend in code. Treat the canvas as the configuration surface and your PHP as the logic. The leverage is in keeping the built-in node set generic and putting domain behaviour in your own node classes behind the Trigger/Action base classes. Every bespoke action you can express as a node is one fewer "can you automate X?" ticket.

Trigger programmatically from application code. The Engine\Dispatcher is the seam that matters day-to-day: you fire workflows from observers, listeners, or controllers with the subject record, rather than relying solely on the panel's trigger nodes. This keeps the automation layer an implementation detail of your app rather than a parallel universe:

// e.g. in a model observer — verify the exact signature against src/Engine/Dispatcher.php
app(Dispatcher::class)->dispatch($workflow, $model);

Wrap this in a feature flag so you can disable an automation without editing the graph.

Custom nodes, with idempotency baked in. Extend the Action base class, implement the handle method, declare your config schema so the ManageNode slide-over can collect inputs, and register the node in config. Then add the label and description to flow.php. Keep the node thin — it should translate config into a call to a service class you already test. That way the node is a five-line adapter and the business logic is testable without booting the canvas.

final class AssignOwnerAction extends Action
{
    public function handle(WorkflowRun $run, array $config): void
    {
        app(AssignOwner::class)->for($run->subject, $config['strategy']);
    }
}

Design every action so running it twice is harmless. Partial graph execution is a real state: a mid-graph failure leaves earlier side effects applied. Idempotency keys on external calls, existence checks before writes, and "send notification" steps that tolerate duplicates are the difference between a retry and an incident.

Separate the queue lane. Give workflows their own queue name and worker pool so a backlog of Wait steps or a slow SaaS call cannot starve your mail or default jobs. Set explicit per-job timeouts. The plugin gives you the runner; capacity planning and failure visibility are yours.

Webhook ingress last. The bundled controller is the entry point, but authentication is a decision you own — verify signatures, use a shared secret, and reject replays. Do not expose it publicly until you have read the controller source and added whatever check it is missing.

Use run history as your observability layer. The runs relation manager on the workflow resource is the first place to look when something "didn't happen", before you touch a log file. Correlate a run back to the triggering record and to your failed-jobs table.

Test the nodes, not the canvas. composer test (Pest), composer analyse (PHPStan level 6), and composer lint are the day-to-day loop. Write Pest tests for each custom node against a testbench boot — the package's own suite shows the pattern. You should not need bun or Vite unless you fork the Svelte side; the canvas ships prebuilt in resources/dist.

Gotchas and Tips

  • "Optionally through the queue" is a half-truth. Wait steps always defer to the queue. Any workflow containing one has a hard runtime dependency on a healthy worker and a driver that tolerates delayed jobs. Validate this in staging, not in prod.
  • Re-run php artisan filament:assets on every upgrade. The v1.6.1 notes literally say the stylesheet was rebuilt and you should run it. Stale assets are a recurring operational step with this package; add it to your deploy script rather than remembering it.
  • Editing a live workflow is the scariest operation in the product. There is no advertised graph versioning for in-flight runs. Assume an edit mutates behaviour for runs already in progress, and adopt a rule: clone, edit, switch over. Confirm the actual semantics in src/Engine/Graph.php before trusting that assumption either way.
  • Nobody prunes the runs table for you. Plan a retention command and supporting indexes from day one. A moderately busy trigger will grow that table faster than you expect because each step is a discrete execution.
  • Tailwind v4 in a Filament panel is a known collision class. If the canvas styling bleeds into your panel (or vice versa), that is the first suspect. The prebuilt resources/dist/flow.css is scoped by convention, not by a guarantee — check before you restyle anything globally.
  • Pin the version and treat panel upgrades as a compatibility event. Dual Filament v4/v5 support means a maintenance matrix on their side and a real chance of breakage on yours. Add "check filament-flow CHANGELOG" to your Filament upgrade checklist.
  • UI copy lives in the package's lang file. Publishing and overriding resources/lang/en/flow.php is cheap; asking the package to change wording is not. Localisation is straightforward once you know this is where it lives.
  • Debugging order for "the workflow didn't fire": run record exists? → queue worker alive and consuming the right queue? → failed jobs table? → node handle() throws on a null subject? → graph config valid? The Dispatcher is quiet by default; add your own logging at the dispatch call site rather than instrumenting the engine.
  • Don't fork the canvas casually. The moment you touch resources/js/, you inherit bun, Vite, svelte-check, vitest, and the obligation to commit built dist files. Stay on the PHP side of the fence unless the visual editor is genuinely the product.
  • Adoption risk is real. 20 stars, zero dependents, no support contract. Budget for internal ownership from day one, name a maintainer, and keep the fork path open. The engineering hygiene (Pest, PHPStan 6, Playwright e2e, a clean patch release with "nothing to do" upgrade notes) is better than the star count implies — but that lowers the odds of silent breakage, it does not remove the bus factor.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
cgv/localized-resource