Harness-engineering nuxt-layouts-pages

Nuxt Layouts and Pages

install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/codex/nuxt-layouts-pages" ~/.claude/skills/intense-visions-harness-engineering-nuxt-layouts-pages-2fa9a2 && rm -rf "$T"
manifest: agents/skills/codex/nuxt-layouts-pages/SKILL.md
source content

Nuxt Layouts and Pages

Structure applications with file-based routing, named layouts, and per-page configuration via definePageMeta

When to Use

  • You are building out the route structure of a Nuxt application
  • You need multiple layouts (default, auth, dashboard) with different navigation or sidebar configurations
  • You want to configure page-level metadata, transitions, middleware, or keepAlive from within the page SFC
  • You are implementing nested routes or catch-all pages

Instructions

Pages — file-based routing:

  1. Create
    .vue
    files in
    pages/
    — the path maps directly to the URL route:
pages/
  index.vue          → /
  about.vue          → /about
  users/
    index.vue        → /users
    [id].vue         → /users/:id
  [...slug].vue      → /* (catch-all)
  1. Place
    <NuxtPage />
    in
    app.vue
    (or within a layout) to render the active page:
<!-- app.vue -->
<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>
  1. Access route params with
    useRoute
    :
const route = useRoute();
const id = route.params.id; // typed if using typed routes

Layouts:

  1. Create layouts in
    layouts/
    . The
    default.vue
    layout is applied automatically. Named layouts require explicit opt-in:
<!-- layouts/default.vue -->
<template>
  <div>
    <AppHeader />
    <slot />
    <AppFooter />
  </div>
</template>
<!-- layouts/dashboard.vue -->
<template>
  <div class="dashboard-grid">
    <DashboardSidebar />
    <main><slot /></main>
  </div>
</template>
  1. Apply a named layout from a page using
    definePageMeta
    :
// pages/admin/users.vue
<script setup lang="ts">
definePageMeta({
  layout: 'dashboard'
})
</script>
  1. Disable the layout entirely for specific pages (e.g., a full-screen login page):
definePageMeta({ layout: false });
  1. Switch layouts dynamically at runtime using
    setPageLayout
    :
const { setPageLayout } = useLayout();
setPageLayout('minimal');

definePageMeta — per-page configuration:

  1. Use
    definePageMeta
    for all page-level config — it is a compiler macro and must be called at the top level of
    <script setup>
    :
definePageMeta({
  layout: 'dashboard',
  middleware: ['auth', 'role-admin'],
  keepalive: true,
  pageTransition: { name: 'slide-left', mode: 'out-in' },
  title: 'User Management', // custom meta field
});

Page transitions:

  1. Configure route transitions globally in
    nuxt.config.ts
    or per-page:
// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    pageTransition: { name: 'page', mode: 'out-in' },
  },
});
/* assets/transitions.css */
.page-enter-active,
.page-leave-active {
  transition: opacity 0.3s;
}
.page-enter-from,
.page-leave-to {
  opacity: 0;
}

Details

Nested routes:

Create a parent page component alongside a subdirectory of the same name to implement nested routing. The parent must include

<NuxtPage />
to render the child:

pages/
  parent.vue         → /parent  (contains <NuxtPage />)
  parent/
    child.vue        → /parent/child

Optional catch-all:

[[...slug]].vue
matches both
/
(optional slug) and
/a/b/c
. Useful for CMS-driven routing.

Typed routes:

Enable

experimental.typedPages
in
nuxt.config.ts
to get full TypeScript inference for route params and query strings:

export default defineNuxtConfig({
  experimental: { typedPages: true },
});

NuxtPage key — force remount on param change:

By default, navigating between

/users/1
and
/users/2
reuses the page component. Force a remount with a
:key
binding:

<NuxtPage :page-key="route => route.fullPath" />

Layout transitions vs. page transitions:

  • pageTransition
    — animates the
    <NuxtPage />
    slot content
  • layoutTransition
    — animates the outer
    <NuxtLayout />
    when switching layouts

Both accept Vue transition options or a boolean.

Custom page meta:

Extend

definePageMeta
with custom fields by augmenting the
PageMeta
interface:

// types/nuxt.d.ts
declare module '#app' {
  interface PageMeta {
    title?: string;
    requiresRole?: string;
  }
}

Then read it in middleware:

to.meta.requiresRole
.

Source

https://nuxt.com/docs/guide/directory-structure/pages

Process

  1. Read the instructions and examples in this document.
  2. Apply the patterns to your implementation, adapting to your specific context.
  3. Verify your implementation against the details and edge cases listed above.

Harness Integration

  • Type: knowledge — this skill is a reference document, not a procedural workflow.
  • No tools or state — consumed as context by other skills and agents.

Success Criteria

  • The patterns described in this document are applied correctly in the implementation.
  • Edge cases and anti-patterns listed in this document are avoided.