Troubleshooting
Work out why nothing moved, the wrong thing moved, or the page jumped.
Work from the outside in: provider, markers, boundary key, winning rule, then layout. Engine internals are the last stop, not the first.
Nothing animates
- Both routes render under the same single <Ssgoi> provider.
- The leaving and arriving route roots both carry data-ssgoi-transition.
- The boundary key changes when that routed region changes. Changing only the id on a node that stays mounted does nothing.
- One route rule matches the pair. If none does, nothing animates: the arriving page resets to the top, and the page you left loses its saved scroll position.
- An edge swipe from either screen edge (iOS swipe-back, Android system back gesture) is detected as a native gesture, and the transition is skipped on purpose.
The wrong region animates
- Find the nearest boundary whose key changed.
- Keep persistent UI outside the inner boundary that remounts.
- Reuse an outer key only while the routes really share that shell.
- Do not create a nested <Ssgoi> provider.
- When a parent and a child boundary both change in one navigation, the outer one owns the transition.
The page jumps or flickers
- Give the element around <Ssgoi> a positioned containing block — the leaving page is re-inserted position: absolute and anchors to it.
- Clip horizontal overflow for transitions that travel past the viewport.
- Give routed pages a full-height background when the design needs one.
Scroll is unexpected
- Identify the rule that won; the scroll policy belongs to that relationship.
- Check middleware if the visible URL and the logical route id differ.
- Remove preserveScroll and confirm the automatic default first.
- Define the config object outside render, or memoize it. A new object on every render rebuilds the context and drops every recorded scroll position.
Layout sanity check
This is the minimum shell the leaving page expects while SSGOI has it re-inserted.
<main className="relative z-0 min-h-dvh overflow-x-clip">
<Ssgoi config={config}>{children}</Ssgoi>
</main>Use
overflow-x: clip, not hidden. Hiding one axis makes the other computed auto, which turns the wrapper itself into the scroll container — and SSGOI then records scroll against the wrong element.If the checklist did not cover it
Agent-oriented checklist: /llms/troubleshooting.txt