<Layout>


Implemented by: vike-react/vike-vue/vike-solid.

You need vike-react/vike-vue/vike-solid to be able to use the Layout setting. If you don't use vike-react/vike-vue/vike-solid then see Without Vike extension.

What are layouts? Pages can have different layouts: for example, if admin panel pages (/admin/product/@id and /admin/user/@id) have a sidebar while marketing pages (/ and /about-us) have a sticky header instead. The admin pages can share the same <Layout> component that includes the sidebar, while the marketing pages can share the <Layout> component that includes the sticky header.

The Layout setting wraps your Page component with another component (the layout component).

<Layout>   ⟸ component defined by the setting "Layout"
  <Page /> ⟸ component defined by the setting "Page"
</Layout>

You can apply a layout as default to all pages:

// /pages/+Layout.js
 
// This layout component is the default layout
export { Layout }
 
// ...

See also: Examples.

You can then override the default layout on a page-by-page basis:

// pages/product/@id/+Layout.js
 
// This layout component overrides the default layout and
// applies to the product page /product/@id
export { Layout }
 
// ...

You can also define a layout for a group of pages:

// /pages/admin/+Layout.js
 
/* This layout applies only to admin pages (/pages/admin/**) such as:
   URL                     FILESYSTEM
   /admin                  /pages/admin/+Page.js
   /admin/user/@id         /pages/admin/user/@id/+Page.js
   /admin/product/@id      /pages/admin/product/@id/+Page.js
*/
export { Layout }
 
// ...

See also <Wrapper> which also wraps <Page>, but for different use cases.

Examples

React / Vue / Solid

Nested Layouts

What are nested layouts? A nested layout is, essentially, when a page has a route with multiple parameters. For example /product/@id/@view:

URL                        id            view
=====================      ====          =======
/product/1337              1337          null
/product/1337/pricing      1337          pricing
/product/42/reviews        42            reviews
/product/42/pricing                   /product/42/reviews
+------------------+                  +-----------------+
| Product          |                  | Product         |
| +--------------+ |                  | +-------------+ |
| | Pricing      | |  +------------>  | | Reviews     | |
| |              | |                  | |             | |
| +--------------+ |                  | +-------------+ |
+------------------+                  +-----------------+

If your nested layout isn't associated with a URL (in other words the pricing page and the reviews page share the same URL /product/42), then you can simply use a stateful component instead of the following.

You can implement a nested layout by using a route with multiple parameters:

// /pages/product/+route.js
 
export default '/product/@id/@view'

You can also use a Route Function for full programmatic flexibility, see this example.

To ensure @view matches a list of pre-defined values, you can use a guard() hook with throw render(404):

// /pages/product/+guard.js
 
import { render } from 'vike/abort'
 
export function guard(pageContext) {
  const { view } = pageContext.routeParams
  if (!['reviews', 'pricing'].includes(view)) {
    throw render(404)
  }
}

You can then use pageContext.routeParams.view to implement the nested layout:

// /pages/product/+Page.js
 
export { Page }
 
import { usePageContext } from 'vike-react/usePageContext' // or 'vike-vue' / 'vike-solid'
 
function Page() {
  const pageContext = usePageContext()
  const nestedLayout = (() => {
    const { view } = pageContext.routeParams
    if (view === 'reviews') return <Reviews />
    if (view === 'pricing') return <Pricing />
  })()
  return <>
     {/* ... */}
       {/* Somewhere deep */ }
       { nestedLayout }
     {/* ... */}
  </>
}

Finally, make sure to use <a href="/product/42/reviews" keep-scroll-position /> (and navigate('/product/42/reviews', { keepScrollPosition: true })) to avoid the browser to scroll to the top.

Once #1459 - Nested Routes is implemented, Vike will automatically preserve the scroll position.

Examples:

Without Vike extension

The following is for users that don't use a UI framework Vike extension (vike-react/vike-vue/vike-solid).

The simple way

A simple way to implement layouts is to manually wrap your <Page> components:

// /pages/index/+Page.js
 
export { Page }
 
import { LayoutDefault } from '../layouts/LayoutDefault'
 
function Page() {
  return <>
    <LayoutDefault>
      {/* ... */}
    </LayoutDefault>
  </>
}
// /pages/admin/+Page.js
 
export { Page }
 
import { LayoutDashboard } from '../layouts/LayoutDashboard'
 
function Page() {
  return <>
    <LayoutDashboard>
      {/* ... */}
    </LayoutDashboard>
  </>
}

With a custom setting

In case you don't use a UI framework Vike extension (vike-react/vike-vue/vike-solid), you can implement the Layout setting yourself by using meta.

Examples:

Nested Layout

See Nested Layouts.

For smooth nested layout navigation, we recommend using Client Routing. (Using Server Routing leads to full page reloads upon nested layout navigation which usually isn't an acceptable UX.)

See also