segue
Documentation

Documentation

Scope and limitations

Learn which navigation, data, accessibility, and recovery tasks your application must handle.

Segue handles one job: it runs consumer-owned visual work before asking Next.js to navigate. Your application owns the design, destination behavior, accessibility integration, and manifest data policy.

Framework support

Segue supports this exact peer range:

  • Next.js >=16.3.1 <17
  • React >=19.2 <20
  • The Next.js App Router

Mount the Provider in a shared layout that remains mounted across the source and destination. Segue stops active work if the Provider unmounts.

Segue doesn't support the Pages Router, other React routers, server-only navigation, or coordinated Route Transitions across a new-document navigation. It can use new-document navigation as recovery, but no Segue visual work survives that fallback.

Route matching and rewrites

Segue resolves the requested URL against the current browser location, removes dot segments and trailing slashes from its pathname, and performs an exact manifest lookup. Query strings and hashes don't affect Preset selection.

Segue doesn't expand dynamic route patterns. Enumerate each concrete browser pathname that needs a Preset:

const segueManifest = defineManifest({
  routes: [
    { path: "/projects/field-study", preset: "project-cover", imagesByRole: {} },
    { path: "/projects/civic-centre", preset: "project-cover", imagesByRole: {} },
  ],
});

Generate this list from CMS or route data before calling defineManifest when hand-maintained paths aren't practical. The generated result must still contain concrete exact paths.

Segue sees the browser URL, not the internal destination behind a Next.js rewrite. If /work/field-study rewrites to /projects/field-study, add /work/field-study to the manifest if links use that public URL. A link that changes only the current query or hash bypasses coordination and continues through Next.js normally.

A static, public manifest

The Provider captures the manifest, route index, and rendition index when it first mounts. Updating its manifest prop doesn't rebuild those indexes. Treat the manifest as static for the browser lifetime; use a new document load when a visitor must receive a newly generated manifest.

You can generate a manifest during a server render or build and pass it to a Client Component. Once hydrated, that generated snapshot is static. Revalidate or regenerate it on the server for later document requests rather than mutating the mounted Provider.

The complete manifest is sent to the browser. It is public data, not an authorization boundary. Don't include secrets, private CMS fields, signed URLs with sensitive credentials, unpublished paths, or any value a visitor isn't allowed to inspect. Authorization for the destination route and image resource must remain independent of Segue.

Keep rendition data to the fields that renderImage needs. It supports JSON-compatible primitives, dense arrays, and plain objects. It rejects cycles, non-finite numbers, functions, class instances, and other non-JSON data.

An assetId identifies an Image Asset. An assetId and profile pair identifies one Image Rendition, and every occurrence of that pair must contain equal rendition data.

Back, forward, and recovery

A coordinated push creates temporary history state before outgoing animation begins. This lets Back cancel the pending visual work. If the in-memory navigation details still exist, Forward can replay the pending navigation; its source element is null, so source-dependent Overrides should decline and allow the destination Preset to run.

Ordinary browser Back and Forward navigations aren't animated by Segue. A navigation to a different pathname records a Route-Transition Entry of { type: "none" }.

After reload, page restoration, or a crash, Segue detects stale temporary history state and tries to return to the origin entry. If a started history traversal doesn't complete within one second, it uses location.replace for the saved origin URL. History preparation, cleanup, and recovery failures are reported through onIssue.

One navigation at a time

Segue coordinates one navigation at a time. Programmatic navigate calls made while it is busy resolve to { status: "ignored", reason: "busy" }.

Segue.Link doesn't expose that result or automatically disable itself. Another different-route Link that requires coordination is ignored while Segue is busy; external and same-path Links remain browser- or Next.js-owned. Make outgoing controls inert or disabled and provide status feedback, as shown in Production integration.

Outgoing work and Next.js navigation have separate timeouts. If the asynchronous Override-to-Preset sequence doesn't settle within transitionTimeoutMs, Segue aborts it and starts navigation; callbacks must not block synchronously. If Next.js navigation doesn't settle within commitTimeoutMs, Segue reports the timeout and uses location.replace for the destination.

Visual and interface behavior

Segue doesn't provide animation markup, CSS, or an animation dependency. Your application owns:

  • Preset markup, visual timing, and responsive behavior
  • Destination Entrance animation after commit
  • Scroll locking and restoration
  • Preventing interaction with outgoing content
  • Status announcements and aria-busy
  • Focus movement after route commit
  • Alternative text and all other destination accessibility

Segue adds aria-hidden="true" to temporary Preset UI because it is decorative. Don't put controls, announcements, or information that a visitor must read inside that container.

Follow the production integration how-to to implement these responsibilities.

initial