Nuxt Pages Plus

repository·main·Indexed 42 days ago

https://github.com/serkodev/nuxt-pages-plus

A Nuxt module (v1.2.0) that extends standard routing to support complex patterns inspired by the Next.js App Router, including Parallel Routes and Modal Routes. It enables rendering multiple independent page views within a single layout using the <PlusParallelPage /> component and provides support for nested named parallel routes and intercepting routes. Compatible with Nuxt 3 (>=3.16.0) and Nuxt 4.

Tokens
13.5K
Snippets
54
Records
67
Agent score
50%

What's inside Nuxt Pages Plus

  1. Overview of nuxt-pages-plus features

    main

    Nuxt Pages Plus is a Nuxt module designed to enable complex routing patterns inspired by the Next.js App Router. Key features include:

    • Parallel Routes: Render multiple pages within a single route, either synchronously or manually.
    • Modal Routes: Navigate to modal routes with real-time URL changes for seamless browsing.
    • File-based Routing: Create named routes directly within your Nuxt project's pages directory.
    • SSR Friendly: Optimized for both Server-Side Rendering (SSR) and Static Site Generation (SSG).
    • Comprehensive Toolkit: Provides extensive components and composables for flexible integration.
    • Flexible Configuration: Allows for global settings or page-specific overrides.
  2. What is Nuxt Pages Plus?

    main

    Nuxt Pages Plus is a Nuxt Module designed to enhance the routing capabilities of Nuxt Pages. It provides out-of-the-box solutions for complex routing scenarios that are otherwise time-consuming to implement using standard file-based routing.

    Key features include:

    • Advanced Routing Patterns: Inspired by Next.js App Router, it brings capabilities like Parallel Routes and Intercepting Routes to the Nuxt ecosystem.
    • Seamless Integration: It operates as a Nuxt Module, utilizing auto-imports and hooks to preprocess routing without breaking the standard Nuxt DX.
    • Developer Tooling: Provides a suite of components, composables, and flexible configurations to handle dynamic and versatile application structures.
  3. Handle missing parallel pages with fallback slots

    main

    When a parallel route is not found, <PlusParallelPage /> can render fallback content using specific slots:

    1. #not-found slot: Renders when the parallel page is not found. This takes precedence over the index slot if both are defined.
    2. #index slot: Renders when the parallel page is not found on the initial render.

    If you want to completely hide the parallel page area when a fallback is triggered instead of showing fallback content, use the hide-fallback prop.

    <!-- Using not-found slot -->
    <PlusParallelPage name="foo">
      <template #not-found>
        <div>Not Found</div>
      </template>
    </PlusParallelPage>
    
    <!-- Using index slot -->
    <PlusParallelPage name="foo">
      <template #index>
        <div>Index</div>
      </template>
    </PlusParallelPage>
    
    <!-- Hiding the view on fallback -->
    <PlusParallelPage name="foo" hide-fallback />
  4. How Parallel Route Fallbacks work

    main

    When a parallel route is requested, Nuxt Pages Plus follows a specific fallback sequence to ensure the UI remains stable.

    On initial page load:

    1. Match URL against ~/pages.
    2. If no match, redirect to fallback.redirect (if configured in nuxt.config.ts).
    3. If no redirect, render the <PlusParallelPage #not-found> slot.
    4. If no #not-found slot, redirect to /~index (or custom index config).
    5. If no index, render the <PlusParallelPage #index> slot.
    6. If all else fails, leave the view empty.

    On route navigation (client-side):

    1. Match target URL against ~/pages.
    2. If no match, redirect to fallback.redirect (if configured).
    3. If no redirect, render the <PlusParallelPage #not-found> slot.
    4. If no #not-found slot, keep the last successful view (prevents UI flickering/disappearance).
  5. Implement Nested Named Parallel Routes

    main

    Nuxt Pages Plus supports nested name file-based routing, allowing you to define multiple levels of parallel route names within a single path. This is useful for complex nested layouts.

    Nested Naming Patterns

    File PathNameGenerated routeDescription
    @foo/@bar/about.vuefoo/bar/aboutnested name
    about@foo/us@bar.vuefoo/bar/about/usnested name in file and folder
    @foo@bar/about.vuefoo/bar/aboutmultiple nested name in folder
    about/us@foo@bar.vuefoo/bar/about/usmultiple nested name in file
  6. Navigate within Modals and handle Nested Modals

    main

    When a modal is open, you can use <PlusModalLink> inside the modal content to navigate to other modal routes. The modal will remain open while the content inside it changes (e.g., browsing through images in a gallery).

    Nested Navigation (Modals within Modals)

    By default, closing a nested modal (a modal opened from within another modal) might return the user to the original background page. To ensure that closing a nested modal returns the user to the previous modal instead of the background page, use the open prop on the <PlusModalLink> that triggers the nested modal.

    Example: Opening a comment modal from an image modal:

    <!-- Inside the Image Modal -->
    <PlusModalLink open :to="`/comments/${id}`">Comments</PlusModalLink>
    <!-- Inside @modal/image/[id].vue -->
    <template>
      <div>
        <img :src="`/image/${id}`" />
        
        <!-- The 'open' prop ensures closing this returns to the image modal, not the home page -->
        <PlusModalLink open :to="`/comments/${id}`">Comments</PlusModalLink>
    
        <button @click="$modalRouter.close()">Close</button>
      </div>
    </template>
  7. Display a Custom Modal UI

    main

    If you are not using <PlusModalPage> and instead want to use your own modal UI (like a UI library component or a custom <Teleport>), do not gate the visibility solely on the current route. Instead, use the isOpen property from useModalRouter().

    Using isOpen ensures the modal only appears when the current history entry actually carries a modal background view, preventing the modal from popping up incorrectly during pending async navigations or when using browser back/forward buttons.

    <script setup>
    const { isOpen } = useModalRouter()
    </script>
    
    <template>
      <div>
        <PlusModalLink to="/info">Show Info Modal</PlusModalLink>
    
        <Teleport v-if="isOpen" to="body">
          <div class="custom-modal">
            <p>I am a custom modal</p>
            <button @click="$modalRouter.close()">Close</button>
          </div>
        </Teleport>
      </div>
    </template>
  8. Use <PlusModalApp /> as the root component for Modal Routes

    main

    When using Modal Routes, <PlusModalApp /> is the recommended root component. It manages the rendering logic so that when a modal is open, the background route (including its specific layout) continues to render behind the modal. When no modal is active, it behaves like a standard Nuxt app by rendering the current route and layout.

    <template>
      <PlusModalApp />
    </template>
  9. Implement a parallel sidebar layout

    main

    To create a layout where a sidebar and a main content area exist in parallel, organize your pages directory such that files in pages/_side/... mirror the structure of your main routes in pages/....

    Key Components:

    1. Fallback Main Route: Use pages/[...all].vue as a fallback for the main content area. This file handles the default view for the main routes that are not explicitly matched by the sidebar structure.
    2. Sidebar Parent View: If you need to wrap the sidebar content in a parent layout, create a pages/_side.vue file. This file must include a <RouterView /> to render the nested sidebar routes.
    <!-- pages/_side.vue -->
    <template>
        <div>
            out side
            <RouterView />
        </div>
    </template>
  10. Add Parallel Routes to your Nuxt project

    main

    Parallel Routes allow you to render multiple independent page views within a single layout or page. To add a parallel route:

    1. Create a directory in ~/pages prefixed with @. For example, @my-parallel.
    2. Add page files inside that directory (e.g., index.vue, about.vue).
    3. Use the <PlusParallelPage /> component to render the parallel route by its name.

    This allows the parallel view to stay in sync with the global router automatically.

    <!-- 1. Directory structure: pages/@my-parallel/index.vue -->
    <template>
      <div>Index @my-parallel</div>
    </template>
    
    <!-- 2. Usage in a layout or page -->
    <template>
      <div>
        <PlusParallelPage name="my-parallel" />
        <slot />
      </div>
    </template>