Core concepts
Onboarding is described as flows of ordered steps. Each step decides for itself whether it is complete — or excluded — by looking at a subject, so progress is always derived from your current data and never stored.
- OnboardingManager — the central store of named flows, the resolver and the persistence store. Resolved as a singleton and reachable through the Onboarding facade.
- Flow — a named, ordered set of steps. Reports overall progress, the current step, sections and a JSON-ready summary.
- Step — a single onboarding task. Its completion and exclusion are decided by closures or declarative helpers that receive the subject.
- GetsOnboarded — a trait for Eloquent models that resolves the model’s flow and binds the model to it.
- Subject — what a flow is evaluated against: an Eloquent Model or any Authenticatable. Without an explicit one, the authenticated user is used.
At a glance
use RoundlyConsulting\Onboarding\Facades\Onboarding;
use RoundlyConsulting\Onboarding\Flow;
use RoundlyConsulting\Onboarding\Step;
// Register once (e.g. in a service provider's boot()).
Onboarding::register(Flow::make('Profile Onboarding')->of([
Step::make('Upload photo')->key('photo')->cta('Upload now')
->route('profile.photo')
->completeWhenFilled('avatar_path'),
Step::make('Add a bio')->key('bio')->optional()
->completeWhenFilled('bio'),
]));
// Read live progress for any subject.
$flow = Onboarding::for($user); // a copy bound to $user — or $user->onboarding()
$flow?->percentageCompleted(); // float
$flow?->currentStep(); // ?Step to resume on
$flow?->toArray(); // JSON-ready summary for a frontendStateless by design
Nothing is persisted — no tables, no flags, no cached progress. Change a step’s rule and every user’s progress reflects it on the next read. Reads never dispatch events either; only an explicit record() call does. If you do want to remember dismissals or completion timestamps, plug in your own OnboardingStore — see Persistence store.
Defaults worth knowing
- A step with no completion rule is complete; a step with no exclusion rule is never excluded.
- An empty flow counts as complete: isCompleted() is true and percentageCompleted() is 100.0.
- Rules receive the bound subject or null, so write closures null-safe — ?User $user and $user?->… — as every example here does.
- Optional steps count toward percentageCompleted() but never block isCompleted().
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.