Link to the code that reproduces this issue
https://github.com/vercel/next-view-transition-example
To Reproduce
- Go to https://view-transition-example.vercel.app/blog
- Click "Read More" on any post
- Notice the avatars transition appropriately
- Click back in the browser
- Notice that the avatars don't transition back
Current vs. Expected behavior
Currently, the view transitions work correctly when navigating using <Link>, router.push(), or router.replace(), but not when navigating using the browser's native navigation tools.
I would expect the transitions to work regardless.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.5.0: Mon Apr 27 20:38:56 PDT 2026; root:xnu-12377.121.6~2/RELEASE_ARM64_T6000
Available memory (MB): 16384
Available CPU cores: 10
Binaries:
Node: 26.2.0
npm: 11.13.0
Yarn: N/A
pnpm: 9.15.4
Relevant Packages:
next: 16.0.10 // There is a newer version (16.2.7) available, upgrade recommended!
eslint-config-next: N/A
react: 19.0.0
react-dom: 19.0.0
typescript: 5.8.2
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Linking and Navigating
Which stage(s) are affected? (Select all that apply)
next dev (local), next start (local), Vercel (Deployed), Other (Deployed)
Additional context
I looked into app-router.tsx but it looks like it already uses startTransition for the popstate handler.
One thing I noticed that might be related is that during the in-app navigation, it renders the component, but when navigating using the browser's native navigation, it doesn't render but must be using a cached version. I don't know if this is related.
I have another application not using SSG and it does re-render the component, but still has the same behavior, so that could be a red herring.
I created the following small hacky component that can be placed in the root layout.tsx which fixes the issue, but it can introduce bugs and I'd prefer if this was fixed at the framework level.
'use client';
import { startTransition, useEffect } from 'react';
import { useRouter } from 'next/navigation';
export function BrowserNavigationTransition() {
const router = useRouter();
useEffect(() => {
const abortController = new AbortController();
window.addEventListener('popstate', (event: PopStateEvent) => {
// 1. Prevent Next.js from processing the standard instant back navigation
event.stopPropagation();
// 2. Wrap the router event inside a transition
startTransition(() => {
// 3. Manually trigger a refresh to update the content based on the new URL
router.refresh();
});
}, {
signal: abortController.signal,
});
return () => abortController.abort();
}, [router]);
return null;
}
Link to the code that reproduces this issue
https://github.com/vercel/next-view-transition-example
To Reproduce
Current vs. Expected behavior
Currently, the view transitions work correctly when navigating using
<Link>,router.push(), orrouter.replace(), but not when navigating using the browser's native navigation tools.I would expect the transitions to work regardless.
Provide environment information
Which area(s) are affected? (Select all that apply)
Linking and Navigating
Which stage(s) are affected? (Select all that apply)
next dev (local), next start (local), Vercel (Deployed), Other (Deployed)
Additional context
I looked into
app-router.tsxbut it looks like it already usesstartTransitionfor the popstate handler.One thing I noticed that might be related is that during the in-app navigation, it renders the component, but when navigating using the browser's native navigation, it doesn't render but must be using a cached version. I don't know if this is related.
I have another application not using SSG and it does re-render the component, but still has the same behavior, so that could be a red herring.
I created the following small hacky component that can be placed in the root
layout.tsxwhich fixes the issue, but it can introduce bugs and I'd prefer if this was fixed at the framework level.