---
title: "Reading progress — Onboarding for Laravel | Roundly"
description: "Completion, the current step, percentages, position and resume — the full Flow reading API with a reference table."
url: https://roundly-consulting.com/open-source/docs/onboarding-for-laravel/reading-progress
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Onboarding for Laravel](https://roundly-consulting.com/open-source/docs/onboarding-for-laravel.md)

# Reading progress

A flow derives everything on the fly from its steps and the bound subject — nothing is stored:

```php
use RoundlyConsulting\Onboarding\Facades\Onboarding;

$flow = Onboarding::for($user);  // a copy bound to $user — or $user->onboarding()

$flow?->title;                   // "Profile Onboarding"
$flow?->isCompleted();           // bool — every required, non-excluded step is complete
$flow?->isInProgress();          // bool — at least one required step remains
$flow?->currentStep();           // the first incomplete Step (the one to resume on), or null
$flow?->steps();                 // Collection<int, Step> visible to this model (excluded steps removed)
$flow?->all();                   // Collection<int, Step> including excluded steps
$flow?->percentageCompleted();   // float across all visible steps, e.g. 66.67
$flow?->sections();              // Collection<int, SectionData> grouped by step group
$flow?->redirectToCurrentStep(); // ?RedirectResponse to the current step's target
$flow?->toArray();               // a JSON-ready array for your API/frontend
$flow?->toData();                // a typed FlowData DTO
```

## Position and resume

```php
// three visible steps, only the first one complete
$flow->count();                 // 3
$flow->completedCount();        // 1
$flow->position();              // 2 — "step 2 of 3"
$flow->currentStepIndex();      // 1 — 0-based, null when complete
$flow->isStarted();             // true — at least one step complete
$flow->isEmpty();               // false
$flow->percentageCompleted();   // 33.33
```

position() is completedCount() + 1, capped at the visible step count (and never below 1) — the human “step N of M” number. currentStepIndex() is the 0-based index of the first incomplete step, so the two can differ when steps are completed out of order:

```blade
<p>Step {{ $flow->position() }} of {{ $flow->count() }}</p>
```

## Flow reference

| Method | Returns | Purpose |
| --- | --- | --- |
| `steps()` | `Collection<int, Step>` | Visible steps — excluded and dismissed steps removed. |
| `all()` | `Collection<int, Step>` | Every step, including excluded ones, bound and ordered. |
| `requiredSteps() / optionalSteps()` | `Collection<int, Step>` | Visible required / optional steps. |
| `step($key) / hasStep($key)` | `?Step / bool` | Find a visible step by its key. |
| `isCompleted()` | `bool` | Every required visible step is complete. |
| `isInProgress()` | `bool` | The opposite of isCompleted(). |
| `isStarted()` | `bool` | At least one visible step is complete. |
| `isEmpty()` | `bool` | No visible steps — an empty flow counts as complete. |
| `currentStep()` | `?Step` | The first incomplete visible step — the one to resume on. |
| `currentStepIndex()` | `?int` | 0-based index of the current step; null when there is none. |
| `position()` | `int` | 1-based “step N” number, capped at count(). |
| `count() / completedCount()` | `int` | Visible steps / completed visible steps. |
| `percentageCompleted()` | `float` | Across all visible steps; 100.0 for an empty flow. |
| `requiredPercentageCompleted()` | `float` | Across required steps only; 100.0 when there are none. |
| `sections() / groups() / section($key)` | `Collection / ?SectionData` | Per-group progress. |
| `redirectToCurrentStep()` | `?RedirectResponse` | A redirect to the current step’s target. |
| `record(?string $key = null)` | `Flow` | Dispatch StepCompleted / FlowCompleted. |
| `dismiss($key)` | `Flow` | Dismiss an optional, dismissible step — through the manager to the store’s markDismissed(). |
| `toArray() / toData()` | `array / FlowData` | Frontend-ready serialization. |

Visible steps exclude those whose exclusion rule matches and, with a store configured, optional steps the subject has dismissed. all() returns every step, bound and ordered.

## 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 crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## 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.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/onboarding-for-laravel.md)
