Commit Graph

6 Commits

Author SHA1 Message Date
Nathan Nguyen 04140e47a3 feat(app-router): promote same-layout ancestor persistence (#1167)
* feat(app-router): promote same-layout ancestor persistence

App Router soft commits previously preserved absent non-slot entries through the merge layer and kept root-layout hard-navigation policy split between browser state and planner. That made same-layout ancestor persistence implicit and allowed unknown root identity to behave like proof of reuse.

The planner now returns explicit preserveElementIds for proven same-root transitions, browser state stores layoutIds from wire metadata, and visible commits preserve only planner-approved ancestors while leaving parallel-slot persistence semantics intact.

Adds coverage for layout id metadata, unknown-root fallback, stale element removal, and visible layout persistence.

* fix(app-router): validate layout persistence proofs

App Router payload metadata treated every string in __layoutIds as planner preservation authority. That let a bad producer, stale payload, or future refactor pass a page, slot, or malformed key as proof for layout ancestor reuse.

The violated invariant is that layout persistence proof must be validated before it reaches the commit planner. Parse __layoutIds through the AppElements wire-key codec and accept only layout keys.

Also add dynamic segment browser coverage for /blog/[slug] navigation, proving param-sensitive layout and page content update while the layout client counter persists.

* fix(app-router): scope boundary layout proofs

HTTP access fallback payloads derived layout metadata from the full route definition. Layout-level access fallbacks can render only ancestor layouts, so the old proof could let the planner preserve child layouts that were absent from the response.

Derive boundary layout metadata from the rendered layout module subset and mark the root boundary unknown when no route layout is rendered.

* docs(app-router): document layout id ordering

Document the ancestor-first layoutIds invariant at the planner snapshot boundary so future payload producers do not break same-layout prefix persistence.
2026-05-12 14:19:21 +01:00
Nathan Nguyen 1d7c031e30 feat(app-router): feed file metadata routes into head output (#891) 2026-04-30 19:38:32 +01:00
Nathan Nguyen 7e5894103f fix: serve metadata routes in dynamic segments (#500)
* fix: serve metadata routes in dynamic segments (opengraph-image, icon, etc.)

Metadata routes like opengraph-image.tsx inside dynamic segments
(e.g., app/blog/[slug]/opengraph-image.tsx) returned 404 because the
runtime matching used strict equality against the servedUrl which
contains literal bracket notation ([slug]).

Two fixes:
- Generate patternParts for metadata routes with dynamic segments so
  the runtime uses matchPattern() instead of strict equality
- Pass extracted params to the metadata function via makeThenableParams()
  matching Next.js behavior where dynamic metadata routes receive { params }

* fix: address review — scope patternParts to dynamic routes, fix indentation

- Only generate patternParts for dynamic metadata routes (static files
  don't use params)
- Add "keep in sync" comment for segment-to-pattern conversion
- Fix mis-indented try/catch braces in generated static metadata code
2026-03-12 18:56:06 +00:00
James Anderson 764a496ce7 add oxfmt formatter (#380)
* add oxfmt formatter: config, scripts, CI, editor setup, docs

* rebuild lockfile

* fix: add Format to required checks list, remove dead ignore pattern

* run fmt

* add format to agents.md again
2026-03-09 14:56:14 +00:00
James Anderson 53257a8630 fix: layout not receiving correct params (#348)
* fix: layout not receiving correct params

* fix: layout not getting correct params on 404
2026-03-08 14:59:06 +00:00
Steve Faulkner 12fea722b6 Initial public release of vinext 2026-02-24 09:29:39 -06:00