Skip to content

Conversation

@huang-julien
Copy link
Member

🔗 Linked issue

close #31204

📚 Description

This PR adds a second parameter to setPageLayout to add or update props to the layout

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 2, 2025

Open in StackBlitz

@nuxt/kit

npm i https://pkg.pr.new/@nuxt/kit@33805

@nuxt/nitro-server

npm i https://pkg.pr.new/@nuxt/nitro-server@33805

nuxt

npm i https://pkg.pr.new/nuxt@33805

@nuxt/rspack-builder

npm i https://pkg.pr.new/@nuxt/rspack-builder@33805

@nuxt/schema

npm i https://pkg.pr.new/@nuxt/schema@33805

@nuxt/vite-builder

npm i https://pkg.pr.new/@nuxt/vite-builder@33805

@nuxt/webpack-builder

npm i https://pkg.pr.new/@nuxt/webpack-builder@33805

commit: 1f465df

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 2, 2025

CodSpeed Performance Report

Merging #33805 will not alter performance

Comparing setLayout (1f465df) with main (1363c12)

Summary

✅ 10 untouched

@cernymatej
Copy link
Member

julien, you are the 🐐🔥

@huang-julien
Copy link
Member Author

@danielroe seems like there's an issue with twoslash. I need to take a look but this is probably a known bug. Can we remove temporarily twoslash from layouts.md ?

@danielroe
Copy link
Member

danielroe commented Dec 4, 2025

I don't think it's a twoslash bug - it's just that twoslash is running in the context of the root nuxt.config.ts (in the monorepo) so if you want strong typing you need to ensure that project has correct types, or you augment the types within the twoslash block so that it's correct

normally when something like this happens, I assume it's probably showing us a type error that would occur in an end user's project

@huang-julien huang-julien marked this pull request as ready for review December 6, 2025 16:27
@huang-julien
Copy link
Member Author

Had to update twoslash as dependency

@coderabbitai
Copy link

coderabbitai bot commented Dec 6, 2025

Walkthrough

Adds support for passing serialisable layout props through setPageLayout and propagating them via route.meta.layoutProps and the NuxtLayout provider. Exposes a NuxtLayouts type and MakeSerializableObject utilities in public typings, updates module-generated typings to include per-layout prop interfaces, merges route.meta.layoutProps into layoutProps at render time, and preserves payload hydration of layout props. Tests and fixtures updated to cover layout props.

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(nuxt): allow updating props with setPageLayout' clearly describes the main change - adding props parameter support to setPageLayout.
Description check ✅ Passed The description relates to the changeset by explaining that a second parameter is added to setPageLayout to update layout props, matching the linked issue #31204.
Linked Issues check ✅ Passed The PR implements the feature requested in #31204: extending setPageLayout to accept a layoutProps parameter that is forwarded to NuxtLayout, with proper typing and hydration support.
Out of Scope Changes check ✅ Passed All changes directly support the primary objective of adding layoutProps to setPageLayout: type augmentation, router integration, hydration support, and updated tests. No unrelated changes detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch setLayout

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3058099 and 1f465df.

📒 Files selected for processing (1)
  • packages/nuxt/src/pages/runtime/utils.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/nuxt/src/pages/runtime/utils.ts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
docs/2.directory-structure/1.app/1.layouts.md (1)

69-81: Documentation correctly demonstrates type augmentation.

The module augmentation examples appropriately show how to declare custom layout types. The pattern using declare module 'nuxt/app' with interface NuxtLayouts is correct and consistent.

Optional enhancement: Consider adding a more advanced example that demonstrates augmenting with actual prop types rather than unknown:

declare module 'nuxt/app' {
  interface NuxtLayouts {
    'custom': { foo?: string, bar?: number }
  }
}

This would help users understand how to define layout-specific prop types for better type safety when calling setPageLayout.

Also applies to: 124-138

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2a91221 and 70ccf27.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (15)
  • docs/2.directory-structure/1.app/1.layouts.md (2 hunks)
  • packages/nuxt/src/app/components/nuxt-layout.ts (1 hunks)
  • packages/nuxt/src/app/composables/router.ts (3 hunks)
  • packages/nuxt/src/app/index.ts (1 hunks)
  • packages/nuxt/src/app/plugins/router.ts (1 hunks)
  • packages/nuxt/src/app/types.ts (1 hunks)
  • packages/nuxt/src/pages/module.ts (2 hunks)
  • packages/nuxt/src/pages/runtime/composables.ts (2 hunks)
  • packages/nuxt/src/pages/runtime/index.ts (1 hunks)
  • test/basic.test.ts (1 hunks)
  • test/bundle.test.ts (1 hunks)
  • test/fixtures/basic-types/app/app-types.ts (1 hunks)
  • test/fixtures/basic-types/app/layouts/with-props.vue (1 hunks)
  • test/fixtures/basic/app/layouts/custom.vue (1 hunks)
  • test/fixtures/basic/app/middleware/sets-layout.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Follow standard TypeScript conventions and best practices

Files:

  • packages/nuxt/src/app/index.ts
  • packages/nuxt/src/app/types.ts
  • test/fixtures/basic/app/layouts/custom.vue
  • test/fixtures/basic-types/app/layouts/with-props.vue
  • packages/nuxt/src/app/components/nuxt-layout.ts
  • packages/nuxt/src/app/plugins/router.ts
  • packages/nuxt/src/pages/runtime/index.ts
  • test/bundle.test.ts
  • packages/nuxt/src/pages/runtime/composables.ts
  • test/fixtures/basic/app/middleware/sets-layout.ts
  • packages/nuxt/src/pages/module.ts
  • packages/nuxt/src/app/composables/router.ts
  • test/fixtures/basic-types/app/app-types.ts
  • test/basic.test.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx,vue}: Use clear, descriptive variable and function names
Add comments only to explain complex logic or non-obvious implementations
Keep functions focused and manageable (generally under 50 lines), and extract complex logic into separate domain-specific files
Remove code that is not used or needed
Use error handling patterns consistently

Files:

  • packages/nuxt/src/app/index.ts
  • packages/nuxt/src/app/types.ts
  • test/fixtures/basic/app/layouts/custom.vue
  • test/fixtures/basic-types/app/layouts/with-props.vue
  • packages/nuxt/src/app/components/nuxt-layout.ts
  • packages/nuxt/src/app/plugins/router.ts
  • packages/nuxt/src/pages/runtime/index.ts
  • test/bundle.test.ts
  • packages/nuxt/src/pages/runtime/composables.ts
  • test/fixtures/basic/app/middleware/sets-layout.ts
  • packages/nuxt/src/pages/module.ts
  • packages/nuxt/src/app/composables/router.ts
  • test/fixtures/basic-types/app/app-types.ts
  • test/basic.test.ts
**/*.vue

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use <script setup lang="ts"> and the composition API when creating Vue components

Files:

  • test/fixtures/basic/app/layouts/custom.vue
  • test/fixtures/basic-types/app/layouts/with-props.vue
**/*.{test,spec}.{ts,tsx,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Write unit tests for core functionality using vitest

Files:

  • test/bundle.test.ts
  • test/basic.test.ts
🧠 Learnings (5)
📚 Learning: 2024-12-12T12:36:34.871Z
Learnt from: huang-julien
Repo: nuxt/nuxt PR: 29366
File: packages/nuxt/src/app/components/nuxt-root.vue:16-19
Timestamp: 2024-12-12T12:36:34.871Z
Learning: In `packages/nuxt/src/app/components/nuxt-root.vue`, when optimizing bundle size by conditionally importing components based on route metadata, prefer using inline conditional imports like:

```js
const IsolatedPage = route?.meta?.isolate ? defineAsyncComponent(() => import('#build/isolated-page.mjs')) : null
```

instead of wrapping the import in a computed property or importing the component unconditionally.

Applied to files:

  • packages/nuxt/src/app/index.ts
  • packages/nuxt/src/app/types.ts
  • packages/nuxt/src/app/components/nuxt-layout.ts
  • packages/nuxt/src/pages/runtime/index.ts
  • packages/nuxt/src/pages/runtime/composables.ts
  • packages/nuxt/src/pages/module.ts
  • packages/nuxt/src/app/composables/router.ts
  • docs/2.directory-structure/1.app/1.layouts.md
📚 Learning: 2024-11-05T15:22:54.759Z
Learnt from: GalacticHypernova
Repo: nuxt/nuxt PR: 26468
File: packages/nuxt/src/components/plugins/loader.ts:24-24
Timestamp: 2024-11-05T15:22:54.759Z
Learning: In `packages/nuxt/src/components/plugins/loader.ts`, the references to `resolve` and `distDir` are legacy code from before Nuxt used the new unplugin VFS and will be removed.

Applied to files:

  • packages/nuxt/src/app/index.ts
  • packages/nuxt/src/pages/module.ts
📚 Learning: 2025-11-25T11:42:16.132Z
Learnt from: CR
Repo: nuxt/nuxt PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-25T11:42:16.132Z
Learning: Applies to **/*.vue : Use `<script setup lang="ts">` and the composition API when creating Vue components

Applied to files:

  • test/fixtures/basic-types/app/layouts/with-props.vue
  • docs/2.directory-structure/1.app/1.layouts.md
📚 Learning: 2024-11-11T12:34:22.648Z
Learnt from: Tofandel
Repo: nuxt/nuxt PR: 0
File: :0-0
Timestamp: 2024-11-11T12:34:22.648Z
Learning: Ensure that AI-generated summaries accurately reflect the key changes in the PR, focusing on notable changes such as the removal of unused imports and variables starting with underscores.

Applied to files:

  • test/bundle.test.ts
  • test/basic.test.ts
📚 Learning: 2025-11-25T11:42:16.132Z
Learnt from: CR
Repo: nuxt/nuxt PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-25T11:42:16.132Z
Learning: Applies to **/e2e/**/*.{ts,tsx,js} : Write end-to-end tests using Playwright and `nuxt/test-utils`

Applied to files:

  • test/fixtures/basic-types/app/app-types.ts
🪛 Biome (2.1.2)
packages/nuxt/src/pages/runtime/composables.ts

[error] 11-13: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
  • GitHub Check: test-fixtures (windows-latest, built, vite-env-api, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (windows-latest, dev, vite, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, rspack, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite-env-api, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, webpack, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite, async, manifest-on, js, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, rspack, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite, default, manifest-off, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, built, vite, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite-env-api, async, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite, default, manifest-on, json, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite, async, manifest-on, js, lts/-1)
  • GitHub Check: test-fixtures (ubuntu-latest, dev, vite, async, manifest-off, json, lts/-1)
  • GitHub Check: release-pkg-pr-new
  • GitHub Check: test-benchmark
  • GitHub Check: test-size
  • GitHub Check: typecheck (windows-latest, bundler)
  • GitHub Check: typecheck (ubuntu-latest, bundler)
  • GitHub Check: code
🔇 Additional comments (15)
test/bundle.test.ts (1)

98-98: LGTM! Expected bundle size increase.

The 1 KB increase in the server bundle size is minimal and expected given the addition of layoutProps functionality.

test/fixtures/basic-types/app/app-types.ts (1)

302-311: LGTM! Comprehensive type-checking coverage.

The test cases effectively verify that setPageLayout recognises named layouts and their associated props, including both valid usage patterns and expected type errors for invalid layouts and incorrect prop types.

test/basic.test.ts (1)

1408-1408: LGTM! Good integration test coverage.

The assertion verifies end-to-end functionality by confirming that middleware-provided layout props render correctly in the DOM, complementing the changes in the middleware fixture.

test/fixtures/basic/app/middleware/sets-layout.ts (1)

3-5: LGTM! Clear demonstration of the new API.

The middleware demonstrates the new setPageLayout signature with layout props, which is then verified in the integration tests to ensure the props propagate correctly to the layout component.

packages/nuxt/src/pages/runtime/index.ts (1)

2-2: LGTM! Appropriate public API expansion.

Adding NuxtLayouts to the public type exports enables users to access layout typing, which is necessary for the type-safe layout props feature.

packages/nuxt/src/app/plugins/router.ts (1)

241-247: LGTM! Correct hydration flow for layout props.

The implementation properly handles layoutProps during hydration by:

  1. Reading initialLayoutProps from the server payload (line 241)
  2. Restoring it to to.meta.layoutProps during hydration (line 247)

This ensures layout props set on the server are correctly transferred to the client and preserved during the initial navigation.

packages/nuxt/src/app/components/nuxt-layout.ts (1)

99-99: LGTM! Props merging enables route-driven layout props.

The LayoutProvider now merges three sources of props:

  1. context.attrs (component-level props)
  2. route.meta.layoutProps (route/middleware-driven props)
  3. { ref: layoutRef } (internal ref)

This merge order allows route-driven props from setPageLayout to override component-level props, which aligns with the feature's intended behaviour.

packages/nuxt/src/app/types.ts (1)

3-3: LGTM! Consistent public API expansion.

Adding NuxtLayouts to the type exports maintains consistency with the public API surface expansion seen in packages/nuxt/src/pages/runtime/index.ts and enables users to access layout typing.

test/fixtures/basic/app/layouts/custom.vue (1)

15-15: LGTM! Layout props integration looks good.

The optional foo prop is correctly defined and rendered, demonstrating the new layout props feature effectively. The implementation follows Vue composition API best practices.

Also applies to: 22-24

packages/nuxt/src/app/index.ts (1)

14-14: LGTM! Public API surface appropriately extended.

The export of NuxtLayouts correctly expands the public type surface to support the new layout props feature.

packages/nuxt/src/pages/runtime/composables.ts (2)

9-13: LGTM! Empty interface is intentional for module augmentation.

The empty NuxtLayouts interface is designed to be augmented at build time with layout-specific typings. This is a standard pattern for runtime-extended types in Nuxt.

Note: The Biome static analysis warning can be safely ignored—this is not a code smell but an intentional design pattern for TypeScript module augmentation.


56-62: LGTM! Router meta augmentation correctly preserves inheritance.

The RouteMeta augmentation properly extends UnwrapRef<PageMeta> whilst adding the internal layoutProps field. The @internal annotation appropriately indicates this is not part of the public API.

test/fixtures/basic-types/app/layouts/with-props.vue (1)

1-11: LGTM! Clean test fixture for layout props.

The component correctly demonstrates typed layout props with a required aProp parameter. The implementation follows Vue composition API best practices with <script setup lang="ts">.

packages/nuxt/src/app/composables/router.ts (1)

269-299: LGTM! Layout props propagation is well-structured across all contexts.

The enhanced setPageLayout correctly:

  • Uses generics to provide type-safe props based on the layout name
  • Propagates layoutProps through server payload (line 281), middleware (line 290), and client route meta (line 297)
  • Guards the useRoute() call (line 295) with !inMiddleware to avoid the warnings mentioned in lines 22-26
  • Maintains backwards compatibility with the optional props parameter

The conditional type signature elegantly handles both typed layouts (when NuxtLayouts is augmented) and fallback to string when no layouts are defined.

packages/nuxt/src/pages/module.ts (1)

5-5: LGTM! Layout typings generation is well-implemented.

The code correctly:

  • Imports genSafeVariableName to ensure valid variable names for layout components
  • Generates imports for all layout files with safe identifiers
  • Builds the NuxtLayouts interface mapping each layout name to InstanceType<typeof Layout>['$props'], which properly extracts Vue component prop types
  • Updates LayoutKey to derive from NuxtLayouts with a string fallback when no layouts exist

The generated typings will provide excellent IntelliSense and type safety for setPageLayout calls.

Also applies to: 622-643

@danielroe
Copy link
Member

weird - the only thing updated in the lockfile was yaml

@huang-julien
Copy link
Member Author

hmmm let me try reverting it. Last time i had to run install for twoslash again.

@danielroe danielroe added this to the 4.3 milestone Dec 16, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
packages/nuxt/src/app/composables/router.ts (3)

270-273: Expand the JSDoc to document the new props parameter.

The JSDoc comment doesn't mention the new optional props parameter or explain how layout props are propagated. Consider adding:

  • A description of the props parameter
  • The serialization constraints on props
  • An example showing the new functionality
🔎 Proposed enhancement to JSDoc
 /**
  * Sets the layout for the current page.
+ * @param layout - The name of the layout to use.
+ * @param props - Optional props to pass to the layout component. Props must be serializable.
  * @since 3.0.0
  */

274-274: Consider simplifying the conditional type for the props parameter.

The condition typeof layout extends Layout in the props parameter type appears redundant. Since layout has type Layout when the generic is known, typeof layout would always be Layout at the type level, making this condition always true. Consider simplifying to:

props?: unknown extends Layout ? never : MakeSerializableObject<NuxtLayouts[Layout]>

This more directly expresses the intent: props are only accepted when Layout is a known key of NuxtLayouts.


281-281: Consider adding a development-mode check to validate layout props are serialisable.

The props parameter uses the MakeSerializableObject type constraint to enforce serializability at compile-time, but this provides no runtime validation. Developers can bypass the type system (e.g., with as any), and non-serialisable values would cause serialization errors during server-side rendering. Adding a console warning in development mode when non-serialisable values are detected would help prevent hydration mismatches, consistent with the existing hydration warnings in this function.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b2240e5 and 3058099.

📒 Files selected for processing (6)
  • docs/2.directory-structure/1.app/1.layouts.md
  • packages/nuxt/src/app/components/nuxt-layout.ts
  • packages/nuxt/src/app/composables/router.ts
  • packages/nuxt/src/app/plugins/router.ts
  • packages/nuxt/src/pages/module.ts
  • packages/nuxt/src/pages/runtime/composables.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/nuxt/src/pages/module.ts
  • packages/nuxt/src/app/components/nuxt-layout.ts
  • docs/2.directory-structure/1.app/1.layouts.md
  • packages/nuxt/src/app/plugins/router.ts
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Follow standard TypeScript conventions and best practices

Files:

  • packages/nuxt/src/app/composables/router.ts
  • packages/nuxt/src/pages/runtime/composables.ts
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,js,jsx,vue}: Use clear, descriptive variable and function names
Add comments only to explain complex logic or non-obvious implementations
Keep functions focused and manageable (generally under 50 lines), and extract complex logic into separate domain-specific files
Remove code that is not used or needed
Use error handling patterns consistently

Files:

  • packages/nuxt/src/app/composables/router.ts
  • packages/nuxt/src/pages/runtime/composables.ts
🧠 Learnings (1)
📚 Learning: 2024-12-12T12:36:34.871Z
Learnt from: huang-julien
Repo: nuxt/nuxt PR: 29366
File: packages/nuxt/src/app/components/nuxt-root.vue:16-19
Timestamp: 2024-12-12T12:36:34.871Z
Learning: In `packages/nuxt/src/app/components/nuxt-root.vue`, when optimizing bundle size by conditionally importing components based on route metadata, prefer using inline conditional imports like:

```js
const IsolatedPage = route?.meta?.isolate ? defineAsyncComponent(() => import('#build/isolated-page.mjs')) : null
```

instead of wrapping the import in a computed property or importing the component unconditionally.

Applied to files:

  • packages/nuxt/src/app/composables/router.ts
  • packages/nuxt/src/pages/runtime/composables.ts
🧬 Code graph analysis (1)
packages/nuxt/src/pages/runtime/composables.ts (1)
packages/nuxt/src/pages/runtime/utils.ts (1)
  • SerializableValue (8-8)
🪛 Biome (2.1.2)
packages/nuxt/src/pages/runtime/composables.ts

[error] 12-14: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

🔇 Additional comments (6)
packages/nuxt/src/pages/runtime/composables.ts (3)

8-9: LGTM! Appropriate import for serializable layout props.

The SerializableValue type import is necessary for the new layoutProps feature and ensures that layout props can be properly serialised for SSR contexts.


10-14: Valid module augmentation pattern for runtime-generated types.

Whilst the static analysis tool flags the empty interface, this is an intentional and valid TypeScript pattern for module augmentation. The comment clearly indicates this interface will be extended at build time with generated layout types. The eslint-disable comment confirms the team is aware of this pattern.


57-63: LGTM! Proper module augmentation for layout props.

The RouteMeta augmentation correctly adds the layoutProps field with an appropriate type for serialisable values. The @internal marking is correct, as this field should be managed through the framework API (setPageLayout()) rather than manipulated directly.

packages/nuxt/src/app/composables/router.ts (3)

288-292: LGTM! Consistent with existing layout handling.

The props are correctly propagated via route metadata in the beforeResolve hook, maintaining consistency with how the layout itself is set. This ensures the props are available during layout rendering.


294-298: LGTM! Props correctly set in non-middleware path.

When not in middleware, the layout props are synchronously set on the route metadata alongside the layout itself. This maintains consistency with the middleware path and ensures props are available regardless of when setPageLayout is called.


7-7: Import sources are correctly configured and properly exported.

The type imports are valid: NuxtLayouts is exported from packages/nuxt/src/pages/runtime/composables.ts and MakeSerializableObject is exported from packages/nuxt/src/pages/runtime/utils.ts.

@danielroe danielroe merged commit b56ec45 into main Dec 23, 2025
102 of 104 checks passed
@danielroe danielroe deleted the setLayout branch December 23, 2025 22:16
This was referenced Dec 23, 2025
Comment on lines +22 to +24
defineProps<{
foo?: string
}>()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @huang-julien, The docs recommend using useAttrs for layout props, I didn't know that we can use defineProps in layouts too. Is this new, or am I missing something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add layoutProps to setPageLayout()

5 participants