- CLAUDE.md 운영 규칙 - wiki/ 정리된 지식 페이지 (Nuxt + Claude Code) - raw/ 원본 자료 - reference/ Nuxt 4.x 공식 문서 Co-authored-by: Cursor <cursoragent@cursor.com>
6.3 KiB
title, head.title, description, navigation.icon
| title | head.title | description | navigation.icon |
|---|---|---|---|
| layouts | layouts/ | Nuxt provides a layouts framework to extract common UI patterns into reusable layouts. | i-vscode-icons-folder-type-view |
::tip{icon="i-lucide-rocket" } For best performance, components placed in this directory will be automatically loaded via asynchronous import when used. ::
Enable Layouts
Layouts are enabled by adding <NuxtLayout> to your app.vue:
<template>
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</template>
To use a layout:
- Set a
layoutproperty in your page with definePageMeta. - Set the
nameprop of<NuxtLayout>. - Set the
appLayoutproperty in route rules.
::note
The layout name is normalized to kebab-case, so someLayout becomes some-layout.
::
::note
If no layout is specified, app/layouts/default.vue will be used.
::
::important
If you only have a single layout in your application, we recommend using app.vue instead.
::
::important
Unlike other components, your layouts must have a single root element to allow Nuxt to apply transitions between layout changes - and this root element cannot be a <slot />.
::
Default Layout
Add a ~/layouts/default.vue:
<template>
<div>
<p>Some default layout content shared across all pages</p>
<slot />
</div>
</template>
In a layout file, the content of the page will be displayed in the <slot /> component.
Named Layout
-| layouts/
---| default.vue
---| custom.vue
Then you can use the custom layout in your page:
<script setup lang="ts">
declare module 'nuxt/app' {
interface NuxtLayouts {
'custom': unknown
}
}
// ---cut---
definePageMeta({
layout: 'custom',
})
</script>
::read-more{to="/docs/4.x/directory-structure/app/pages#page-metadata"}
Learn more about definePageMeta.
::
You can directly override the default layout for all pages using the name property of <NuxtLayout>:
<script setup lang="ts">
// You might choose this based on an API call or logged-in status
const layout = 'custom'
</script>
<template>
<NuxtLayout :name="layout">
<NuxtPage />
</NuxtLayout>
</template>
If you have a layout in nested directories, the layout's name will be based on its own path directory and filename, with duplicate segments being removed.
| File | Layout Name |
|---|---|
~/layouts/desktop/default.vue |
desktop-default |
~/layouts/desktop-base/base.vue |
desktop-base |
~/layouts/desktop/index.vue |
desktop |
For clarity, we recommend that the layout's filename matches its name:
| File | Layout Name |
|---|---|
~/layouts/desktop/DesktopDefault.vue |
desktop-default |
~/layouts/desktop-base/DesktopBase.vue |
desktop-base |
~/layouts/desktop/Desktop.vue |
desktop |
:link-example{to="/docs/4.x/examples/features/layouts"}
Changing the Layout Dynamically
You can also use the setPageLayout helper to change the layout dynamically:
<script setup lang="ts">
declare module 'nuxt/app' {
interface NuxtLayouts {
'custom': unknown
}
}
// ---cut---
function enableCustomLayout () {
setPageLayout('custom')
}
definePageMeta({
layout: false,
})
</script>
<template>
<div>
<button @click="enableCustomLayout">
Update layout
</button>
</div>
</template>
You can also set layouts for specific routes using the appLayout property in route rules:
export default defineNuxtConfig({
routeRules: {
// Set layout for specific route
'/admin': { appLayout: 'admin' },
// Set layout for multiple routes
'/dashboard/**': { appLayout: 'dashboard' },
// Disable layout for a route
'/landing': { appLayout: false },
},
})
::tip This is useful when you want to manage layouts centrally in your configuration rather than in each page file, or when you need to apply layouts to routes that don't have corresponding page components (such as catchall pages which might match many paths). ::
:link-example{to="/docs/4.x/examples/features/layouts"}
Passing Props to Layouts :badge[+4.4]
You can pass props to layouts in several ways.
Via definePageMeta
Use the object syntax for the layout property to pass props directly from your page:
::code-group
<script setup lang="ts">
definePageMeta({
layout: {
name: 'panel',
props: {
sidebar: true,
title: 'Dashboard',
},
},
})
</script>
<script setup lang="ts">
const props = defineProps<{
sidebar?: boolean
title?: string
}>()
</script>
<template>
<div>
<aside v-if="sidebar">
Sidebar
</aside>
<main>
<h1>{{ title }}</h1>
<slot />
</main>
</div>
</template>
::
::tip
Props are fully typed based on your layout's defineProps. You'll get autocomplete and type-checking in your editor.
::
Via setPageLayout
You can also pass props when changing the layout dynamically with setPageLayout:
setPageLayout('panel', { sidebar: true, title: 'Dashboard' })
Overriding a Layout on a Per-page Basis
If you are using pages, you can take full control by setting layout: false and then using the <NuxtLayout> component within the page.
::code-group
<script setup lang="ts">
definePageMeta({
layout: false,
})
</script>
<template>
<div>
<NuxtLayout name="custom">
<template #header>
Some header template content.
</template>
The rest of the page
</NuxtLayout>
</div>
</template>
<template>
<div>
<header>
<slot name="header">
Default header content
</slot>
</header>
<main>
<slot />
</main>
</div>
</template>
::
::important
If you use <NuxtLayout> within your pages, make sure it is not the root element (or disable layout/page transitions).
::