definePageMeta is a compiler macro that you can use to set metadata for your page components located in the pages/ directory (unless set otherwise). This way you can set custom metadata for each static or dynamic route of your Nuxt application.
<script setup lang="ts">
definePageMeta({
  layout: 'default',
})
</script>
export function definePageMeta (meta: PageMeta): void
interface PageMeta {
  validate?: ((route: RouteLocationNormalized) => boolean | Promise<boolean> | Partial<NuxtError> | Promise<Partial<NuxtError>>)
  redirect?: RouteRecordRedirectOption
  name?: string
  path?: string
  props?: RouteRecordRaw['props']
  alias?: string | string[]
  pageTransition?: boolean | TransitionProps
  layoutTransition?: boolean | TransitionProps
  viewTransition?: boolean | 'always'
  key?: false | string | ((route: RouteLocationNormalizedLoaded) => string)
  keepalive?: boolean | KeepAliveProps
  layout?: false | LayoutKey | Ref<LayoutKey> | ComputedRef<LayoutKey>
  middleware?: MiddlewareKey | NavigationGuard | Array<MiddlewareKey | NavigationGuard>
  scrollToTop?: boolean | ((to: RouteLocationNormalizedLoaded, from: RouteLocationNormalizedLoaded) => boolean)
  [key: string]: unknown
}
metaPageMetanamestringpages/ directory.pathstringpropsRouteRecordRaw['props']params as props passed to the page component.aliasstring | string[]/users/:id and /u/:id. All alias and path values must share the same params.keepaliveboolean | KeepAlivePropstrue when you want to preserve page state across route changes or use the KeepAliveProps for a fine-grained control.keyfalse | string | ((route: RouteLocationNormalizedLoaded) => string)key value when you need more control over when the <NuxtPage> component is re-rendered.layoutfalse | LayoutKey | Ref<LayoutKey> | ComputedRef<LayoutKey>false in case the default layout needs to be disabled.layoutTransitionboolean | TransitionPropsfalse to disable the layout transition.middlewareMiddlewareKey | NavigationGuard | Array<MiddlewareKey | NavigationGuard>definePageMeta. Learn more about route middleware.pageTransitionboolean | TransitionPropsfalse to disable the page transition.viewTransitionboolean | 'always'prefers-reduced-motion: reduce (recommended). If set to always, Nuxt will always apply the transition.redirectRouteRecordRedirectOptionvalidate(route: RouteLocationNormalized) => boolean | Promise<boolean> | Partial<NuxtError> | Promise<Partial<NuxtError>>statusCode/statusMessage to respond immediately with an error (other matches will not be checked).scrollToTopboolean | (to: RouteLocationNormalized, from: RouteLocationNormalized) => boolean~/app/router.options.ts (see custom routing) for more info.[key: string]anymeta object.The example below demonstrates:
key can be a function that returns a value;keepalive property makes sure that the <modal> component is not cached when switching between multiple components;pageType as a custom property:<script setup lang="ts">
definePageMeta({
  key: route => route.fullPath,
  keepalive: {
    exclude: ['modal'],
  },
  pageType: 'Checkout',
})
</script>
The example below shows how the middleware can be defined using a function directly within the definePageMeta or set as a string that matches the middleware file name located in the middleware/ directory:
<script setup lang="ts">
definePageMeta({
  // define middleware as a function
  middleware: [
    function (to, from) {
      const auth = useState('auth')
      if (!auth.value.authenticated) {
        return navigateTo('/login')
      }
      if (to.path !== '/checkout') {
        return navigateTo('/checkout')
      }
    },
  ],
  // ... or a string
  middleware: 'auth',
  // ... or multiple strings
  middleware: ['auth', 'another-named-middleware'],
})
</script>
A custom regular expression is a good way to resolve conflicts between overlapping routes, for instance:
The two routes "/test-category" and "/1234-post" match both [postId]-[postSlug].vue and [categorySlug].vue page routes.
To make sure that we are only matching digits (\d+) for postId in the [postId]-[postSlug] route, we can add the following to the [postId]-[postSlug].vue page template:
<script setup lang="ts">
definePageMeta({
  path: '/:postId(\\d+)-:postSlug',
})
</script>
For more examples see Vue Router's Matching Syntax.
You can define the layout that matches the layout's file name located (by default) in the layouts/ directory. You can also disable the layout by setting the layout to false:
<script setup lang="ts">
definePageMeta({
  // set custom layout
  layout: 'admin',
  // ... or disable a default layout
  layout: false,
})
</script>