The Onboarding facade
RoundlyConsulting\Onboarding\Facades\Onboarding is the recommended entry point: a final, thin facade over the OnboardingManager singleton — the central store of named flows, the per-subject resolver and the persistence store:
use RoundlyConsulting\Onboarding\Facades\Onboarding;
use RoundlyConsulting\Onboarding\Flow;
use RoundlyConsulting\Onboarding\Step;
// Register flows — usually in a service provider's boot()
Onboarding::register(Flow::make('Profile Onboarding')->of([Step::make('Upload photo')]));
Onboarding::register('user', UserOnboarding::class);
Onboarding::flow('team')->add('Invite your team')->completeWhenHas('members');
// Read for a subject — every call returns its own copy, bound to that subject
Onboarding::for($user)?->percentageCompleted();
Onboarding::for($user, 'team')?->currentStep();
Onboarding::for($user)?->dismiss('add-bio');
// Choose the flow per subject
Onboarding::resolveUsing(fn ($subject) => $subject?->isAdmin() ? 'admin' : 'default');
Onboarding::resolveFor($user);
// Inspect and edit the registry
Onboarding::find('team'); // the registered definition
Onboarding::has('team');
Onboarding::all();
Onboarding::forget('team');
Onboarding::flush();
// Persistence
Onboarding::useStore(DatabaseOnboardingStore::class);
Onboarding::store();
Onboarding::hasStore();Every method
| Method | Returns | Purpose |
|---|---|---|
register($key, $flow = null) | OnboardingManager | Register a Flow, an array of steps or a Flow class string — under the default key when given one argument. |
flow($key) | Flow | Create, register and return an empty flow under the key (replaces an existing one). |
for($subject, ?string $key = null) | ?Flow | A copy of the subject’s flow, bound to it — the key’s flow, or without a key the resolver’s choice, else the default. |
find($key, $default = null) | ?Flow | The registered definition itself (unbound), or $default. |
has($key) | bool | Whether a flow is registered under the key. |
forget($key) | OnboardingManager | Remove one flow. |
flush() | OnboardingManager | Remove all flows and clear the resolver. |
all() | Collection<string, Flow> | Every registered flow, keyed by its key. |
resolveUsing($resolver) | OnboardingManager | Register a closure that maps a subject to a flow key. |
resolveFor($subject, ?string $fallback = null) | ?Flow | A copy of the resolver’s flow bound to the subject, otherwise the fallback key’s flow (default) — without a fallback, the same as for($subject). |
useStore(OnboardingStore|string $store) | OnboardingManager | Configure persistence — an instance, or a class resolved through the container on first use. |
store() / hasStore() | ?OnboardingStore / bool | The store in use (useStore()’s, else a container binding) / whether one is configured, without resolving it. |
Onboarding::fake() | OnboardingFake | Facade only: swap in the recording fake — see Testing. |
The assert*() and seed*() methods in the facade’s docblock exist only after Onboarding::fake() — see Testing.
Copies, not shared instances
for(), resolveFor() and the model trait each return their own copy of the registered flow, bound to the subject — flows read for two users never share state, and the registered definition stays unbound. find() is the exception: it hands back the definition itself, for adding steps at boot.
Model shorthand
The GetsOnboarded trait and Flow::dismiss() go through the same manager, so they behave identically and Onboarding::fake() sees them. $user->onboarding() is Onboarding::resolveFor($user, $user->defaultOnboardingKey()) — the resolver first, the model’s default key as the fallback — and $user->resolvedOnboarding() is Onboarding::for($user).
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.