Next.js Engine v2.6.2 — Runtime Stability & High-Refresh Correctness
Status: Ready for release Release type: Compatibility + correctness patch Previous patch: v2.6.1 Release range:
c82fe8b6~9e766b5fRecommended tag:Release-v2.6.2
v2.6.2 is the stability release for the v2.6 generation of Next.js Engine. It fixes EngineScroll correctness issues, hardens Transitions+ and React 19 hydration behavior, improves Overlay/mobile compatibility, adds real Chromium/Firefox/WebKit validation, and fixes EngineCanvas timing on high-refresh displays.
The EngineCanvas fix is especially important for 90/120/144+ Hz devices: the RAF loop was already display-driven, but surrounding logic still made 60 Hz assumptions. v2.6.2 adds refresh-aware timing, display-relative adaptive quality, a stable elapsed clock, and synchronized Canvas 2D presentation by default.
What changed
- EngineScroll: Range/Timeline DOM-id resolution, late mounts, moving boundaries, progressive viewport focus, physical velocity, resize invalidation, URL/hash handling, snapping, SSR safety, and subscriber isolation were fixed.
- EngineTransitions+: cross-browser fallbacks were hardened, shared transition names became collision-safe, same-URL stalls were removed, invalid complex animation paths fail safely, and
run()is now safe from React lifecycle effects. - React / Next.js: generated Engine CSS is deterministic and hydration-safe, Overlay portals hydrate consistently, EngineNav is rewrite-safe and segment-aware, and reduced-motion handling no longer creates first-render mismatches.
- EngineOverlay / mobile: live
lockScrollchanges now work while an overlay is open, and Popover positioning usesvisualViewportwhere available. - EngineCanvas: real RAF cadence is measured, 60/90/120/144/165/180/200/240 Hz displays are recognized, adaptive DPR follows the display target, callback timing exposes stable elapsed/FPS data, pause/resume timing is corrected, and
desynchronizedCanvas 2D is now opt-in. - Validation: dedicated v2.6.2 regression coverage now runs alongside real Chromium, Firefox, and WebKit Playwright tests.
Commit summary
Commit | Change / fix |
|---|---|
| EngineScroll v2.6.2 correctness pass. Fixed normal |
| Cross-browser + hydration hardening. Added safer Transitions+ fallbacks, deterministic generated CSS, hydration-safe styles/overlays/navigation, mobile viewport fixes, secured v2.6.2 dependency metadata, and React/Next compatibility regression coverage. |
| Transitions+ lifecycle fix. |
| Real-browser harness stabilization. Fixed the compatibility test route and interaction flow so Chromium, Firefox, and WebKit exercise the actual Engine runtime reliably. |
| EngineCanvas high-refresh fix. Added |
| Public API + release documentation finish. Documented high-refresh behavior, exported the new EngineCanvas frame-info type, and folded the Canvas fix into the official v2.6.2 release notes. |
Full v2.6.2 implementation range: c82fe8b6 ~ 9e766b5f.
EngineScroll fixes
v2.6.2 makes EngineScroll target resolution and runtime state substantially more predictable.
Range and Timeline now follow the same target semantics as navigation:
registered EngineScroll point
↓ when missing
normal DOM #id
↓
alignment + offsetUnregistered DOM targets are no longer permanently cached as missing, so lazy/Suspense content can mount later. Plain DOM boundaries are treated as live geometry so layout movement is reflected without rebuilding a Timeline.
viewport.current now defaults to progressive document-aware focus instead of permanent screen center. Applications that intentionally need the old behavior can use:
EngineScroll.setFocus("center");Velocity remains based on physical scroll movement rather than logical focus movement. Resize/orientation invalidation, #-es? protocol matching, failed-target URL intent, snap ownership, standalone directional snap, SSR hash handling, and subscriber isolation were also corrected.
EngineTransitions+ and browser compatibility
Complex presets no longer depend on CSS typed multiplication such as calc(-1 * 10deg). Values are calculated in JavaScript and emitted as ordinary CSS values, reducing browser-specific parsing risk.
Shared-element transition names now include a deterministic hash so different source ids cannot collapse to the same sanitized view-transition-name.
Transition fallback order is now safe:
requested native preset
↓ failure / unavailable
safe fade / Web Animations fallback
↓ unavailable
normal update or navigationSame-URL animated navigation no longer waits for an impossible URL mutation. Errors from transition update callbacks are preserved instead of being hidden by transition cleanup.
useEngineTransitions().run() also yields out of React's active lifecycle stack before entering the synchronous transition snapshot, fixing the React 19 flushSync was called from inside a lifecycle method warning.
EngineCanvas high-refresh fix
The high-refresh bug was not a literal 60 FPS cap: EngineCanvas already used requestAnimationFrame. The problem was that several surrounding assumptions were still designed around 60 Hz.
Refresh-aware frame clock
EngineCanvas now measures recent RAF intervals and estimates common display refresh rates including:
60 / 72 / 75 / 90 / 100 / 120 / 144 / 165 / 180 / 200 / 240 HzDropped frames are handled without immediately misclassifying a 120 Hz display as 60 Hz.
Adaptive DPR follows the display
The previous fixed thresholds treated ~60 FPS as healthy even on a 120 Hz panel. The default target is now display-relative:
<EngineCanvas adaptive adaptiveTargetFps="display" />An explicit target such as adaptiveTargetFps={60} remains available when an application intentionally wants a lower rendering budget.
Stable callback timing
onDraw keeps its existing arguments and gains a backward-compatible fifth frame-info value:
onDraw={(context, canvas, delta, frame, timing) => {
const seconds = timing.elapsed * .001;
}}timing includes:
interface EngineCanvasFrameInfo {
timestamp: number;
delta: number;
elapsed: number;
fps: number;
averageFps: number;
refreshRate: number;
}The first frame after startup/resume now reports delta = 0 instead of a fake ~16 ms frame. Hidden/offscreen pause time is excluded from active elapsed animation time.
Normal Canvas 2D presentation is synchronized by default; low-latency users can explicitly opt into desynchronized.
The product demo also exposed why absolute time must not be calculated as frame * delta: variable 120 Hz intervals can make that clock jump backward or forward. Consumers should use timing.elapsed or accumulate delta instead.
React 19 / Next.js / Overlay stability
Generated Engine CSS is now serialized deterministically so equivalent server/client rule sets produce the same stylesheet ordering. Hydration adopts the exact server-emitted stylesheet before client reconciliation, and later client-generated rules can flush without setting React state during another component's render.
Initially-open Dialog, Drawer, and Popover surfaces no longer choose a portal target during SSR/first hydration. EngineNav keeps pathname-derived state hydration-safe under rewrites and matches route segments correctly instead of using unsafe string-prefix matching.
Overlay lockScroll now responds while an overlay remains open. Popovers use window.visualViewport when available, improving placement around software keyboards, browser chrome, and zoomed mobile viewports.
EngineScroll also leaves browser/Next.js history restoration ownership alone instead of globally forcing history.scrollRestoration = "manual".
CI and verification
v2.6.2 includes dedicated regression checks for EngineScroll, Transitions+, React/Next compatibility, and EngineCanvas high-refresh timing.
EngineCanvas smoke coverage includes:
- 60 Hz cadence;
- 120 Hz cadence;
- 144 Hz cadence;
- dropped-frame refresh detection;
- pause/resume elapsed-time behavior;
- refresh-relative adaptive thresholds.
The real-browser Playwright matrix passes in:
Chromium
Firefox
WebKitThe final Engine runtime CI also passes smoke tests, TypeScript checking, the production Next.js integration build, and client bundle reporting. main-empty has synchronized the v2.6.2 package state.
Compatibility / migration notes
v2.6.2 is a patch release and does not require a broad migration.
The intentional behavior changes are:
viewport.currentdefaults to progressive focus; useEngineScroll.setFocus("center")for the historical permanent-center definition.- Canvas 2D
desynchronizedis now opt-in. - Code deriving absolute animation time should use
timing.elapsedor accumulateddelta, neverframe * delta.
Existing four-argument EngineCanvas onDraw callbacks remain valid. Transitions+ browser fallback behavior is automatic. No migration is required for ordinary Dialog, Drawer, Popover, Range, Timeline, registered points, or Engine links.
Release baseline
Package: nextjs-engine 2.6.2
Next.js: ^16.3.3
Tag: Release-v2.6.2
Range: c82fe8b6 ~ 9e766b5fMaintainer publishing checklist
- Set package version to
2.6.2. - Move Next.js minimum to
^16.3.3. - Add EngineScroll v2.6.2 regression coverage.
- Add Transitions+ compatibility/lifecycle regression coverage.
- Add EngineCanvas high-refresh regression coverage.
- Add React/Next compatibility smoke coverage.
- Add Chromium / Firefox / WebKit Playwright validation.
- Confirm final Engine runtime CI is green.
- Confirm Chromium, Firefox, and WebKit compatibility jobs are green.
- Confirm
main-emptycontains the synchronized v2.6.2 package state. - Create/tag
Release-v2.6.2. - Attach source/package assets if distributed like v2.5.0.
- Publish this document as the GitHub Release body.
Short release summary
Next.js Engine v2.6.2 is a v2 runtime stability patch focused on real browser and display behavior: EngineScroll target/focus correctness, lifecycle-safe Transitions+, deterministic React 19 hydration, safer Overlay/Nav/mobile behavior, and refresh-aware EngineCanvas rendering for 60/90/120/144+ Hz displays. It also adds real Chromium/Firefox/WebKit validation and dedicated high-refresh regression tests.