OpenCut Web App Scroll Restoration with TanStack Router

The OpenCut web client enables automatic scroll restoration by setting scrollRestoration: true when creating the TanStack Router instance in apps/web/src/router.tsx, allowing the single-page application to mimic native browser back/forward scroll behavior.

The OpenCut repository utilizes TanStack Router (the modern successor to React Router) to handle client-side navigation in its web application. By configuring a single boolean flag during router initialization, the application preserves user scroll positions across route changes, eliminating the need for custom scroll management code while maintaining consistency between server-side rendering and client hydration.

How Scroll Restoration Works in OpenCut

The implementation relies on TanStack Router's built-in scroll manager, which activates automatically when the router is instantiated with the appropriate configuration. This system captures viewport offsets and restores them during history navigation without additional dependencies or manual event listeners.

Router Configuration

In apps/web/src/router.tsx, the getRouter() function constructs the router instance using createTanStackRouter from @tanstack/react-router. The configuration object includes the routeTree imported from the auto-generated file and explicitly sets scrollRestoration: true to enable the feature globally.

// apps/web/src/router.tsx
import { createRouter as createTanStackRouter } from '@tanstack/react-router';
import { routeTree } from './routeTree.gen';

export function getRouter() {
  const router = createTanStackRouter({
    routeTree,
    scrollRestoration: true,   // ← enables automatic scroll restore
    defaultPreload: 'intent',
    defaultPreloadStaleTime: 0,
  });

  return router;
}

Scroll Management Mechanics

When scrollRestoration is enabled, TanStack Router injects a scroll manager that records the scroll offset of each route upon navigation away. On subsequent visits—whether through browser back/forward buttons or programmatic navigation—the manager retrieves the saved offset and restores the viewport position before rendering completes. This logic handles edge cases including hash navigation, nested routes, and browser history navigation automatically, executing consistently during both client-side navigation and server-side rendering hydration.

Configuring Scroll Behavior

While the global setting applies to all routes by default, OpenCut supports granular control through per-route overrides and imperative APIs for specific interaction patterns.

Disabling Restoration for Specific Routes

For pages like infinite-scroll feeds where restoring previous positions creates poor user experience, override the default behavior by setting scrollRestoration: false in the route definition.

// apps/web/src/routes/feed.tsx
import { createFileRoute } from '@tanstack/react-router';

export const Route = createFileRoute('/feed')({
  component: FeedPage,
  // Turn off restoration only for this route
  scrollRestoration: false,
});

Manual Scroll Reset

To programmatically scroll to the top regardless of saved history, components can access the router instance via useRouter and invoke the resetScroll() method.

import { useRouter } from '@tanstack/react-router';
import { useEffect } from 'react';

export function SomePage() {
  const router = useRouter();

  useEffect(() => {
    // Force scroll to top when this page mounts
    router.resetScroll();
  }, [router]);

  return <div>…</div>;
}

Key Source Files

Several files define the scroll restoration architecture in the OpenCut codebase:

Summary

  • OpenCut uses TanStack Router with scrollRestoration: true configured in apps/web/src/router.tsx to enable automatic scroll position preservation across navigation events.
  • The scroll manager automatically records and restores viewport offsets during back/forward navigation without requiring custom event listeners or state management.
  • Developers can disable restoration for individual routes by setting scrollRestoration: false in the route configuration object, useful for infinite-scroll feeds or dynamic content.
  • The imperative API via router.resetScroll() allows components to force scroll-to-top behavior regardless of saved history state.
  • The implementation works consistently across client-side navigation and SSR hydration phases, ensuring uniform behavior for all users.

Frequently Asked Questions

Does OpenCut use React Router or TanStack Router for scroll restoration?

The OpenCut web application uses TanStack Router, configured in apps/web/src/router.tsx with the scrollRestoration: true option to handle scroll position management automatically. TanStack Router is the modern successor to React Router and provides this functionality as a built-in configuration option rather than requiring separate packages or manual implementation.

How do I disable scroll restoration for a specific page in OpenCut?

Set scrollRestoration: false in the route configuration object when defining the file route using createFileRoute. This overrides the global setting from router.tsx for that specific path, preventing the router from restoring previous scroll positions when users navigate back to this route, which is particularly useful for feeds or dynamically updating lists.

Can I programmatically scroll to the top of the page in OpenCut?

Yes. Import useRouter from @tanstack/react-router and call router.resetScroll() inside a useEffect hook or event handler. This method forces the viewport to the top regardless of any saved scroll position in the browser history, allowing components to control scrolling behavior imperatively when needed.

Where is the scroll restoration configured in the OpenCut codebase?

The global configuration resides in apps/web/src/router.tsx within the getRouter() function, where createTanStackRouter receives the scrollRestoration: true parameter alongside the routeTree. Individual routes can override this setting in their respective route definition files, such as apps/web/src/routes/feed.tsx for route-specific behavior.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →