When users go off-script

resumeAt, handoffRoutes, pauseRoutes.

Why this exists

Because the guide points at real controls, users operate them before the step that describes them. When that navigates, every anchor on the old page disappears at once, and a naive tour dies on a screen the user is no longer looking at.

These three fields are the difference between a tour that survives real behaviour and one that only works if you follow it exactly.

The three fields

PropTypeDefaultDescription
resumeAt{ pathname; stepIndex }[]They got ahead of the guide — catch up. Forward only.
handoffRoutes{ pathname; flowId }[]Another guide covers this route — switch to it.
pauseRoutesstring[]Nobody covers this route — sleep, keep their place.

resumeAt

The user clicks “Create manually” while the guide is still describing the cards above it. Landing on the form resumes at the first form step.

resumeAt: [{ pathname: "/questions/new", stepIndex: 6 }]

handoffRoutes

Some routes are a different way of doing the same job, not a wrong turn. Writing a question by hand and generating one with AI are siblings. Choosing the second mid-tour should switch guides, not punish the user.

handoffRoutes: [{ pathname: "/questions/ai", flowId: "create-with-ai" }]

pauseRoutes

The tour goes dormant: no overlay, no anchor hunting, no “we lost the step” message. Returning to a covered route resumes on the same step.

pauseRoutes: ["/settings", "/billing"]

Rules and precedence

Evaluated in this order, in one place:

  • handoff — another guide owns this route
  • pause — nobody covers it
  • resume — the user got ahead

Any branch in your UI needs steps, a resumeAt, a handoffRoutes, or a pauseRoutes entry. This is the failure mode neither the lint check nor the browser audit can catch, because every anchor genuinely exists — just not on the page the user chose.