Skip to content

16 — Layouts reference

Nuxt layouts wrap pages with shared chrome (header, sidebar, footer, modals). This repo has six layouts; pick the right one when adding a new page.

The layout files

layouts/
├── default.vue            ← main app chrome
├── error.vue              ← Nuxt error page
├── fourOhOne.vue          ← chrome-less, for transitional / 404-ish surfaces
├── onBoard.vue            ← onboarding pages (stripped chrome)
├── someliNetwork.vue      ← Someli Network section
└── specialOffer.vue       ← promotional / corporate-offer pages

Reference: layout selection in Vue 2 + Nuxt 2 is via layout: '<name>' on the page component:

export default {
  layout: 'onBoard',
  // …
}

If you don't set layout, you get default.vue.

When to use each

Layout Use for
default The main authenticated app: content planner, dashboard, settings, billing, brand kit. Comes with header + sidebar + impersonation banner + welcome modal + the global toast container.
onBoard Onboarding step pages: Organisationprofile, subjects_services, goals_objectives, chaptername, brandkit (in onboarding context), payment. Strips the main-app chrome so the onboarding wizard is the focus. Used by 8 pages.
fourOhOne Pages that are loaded transiently and shouldn't show full chrome: redirect.vue, callback handlers, error-ish surfaces. Used by ~15 pages — the most common non-default layout. The name is misleading: it's not exclusively a 404 layout.
someliNetwork The Someli Network section. Used by pages/someli_network/. Verify with the team the exact scope.
specialOffer Promotional / corporate-offer pages. Used by pages/special_offer/, pages/corporate_offer/. Distinct visual treatment for marketing/sales surfaces.
error Nuxt's error page. Mounted automatically when a page throws or 404s. Don't layout: 'error' from a normal page — it's used by error.vue itself, which Nuxt routes through.

Empirical usage

Grepping the codebase for layout: '<name>' declarations:

Layout Pages declaring it
fourOhOne ~15 pages (most non-app pages)
onBoard ~8 pages (the onboarding steps)
specialOffer 2 pages
someliNetwork 1 page
admin 1 page — but layouts/admin.vue does not exist. This is a bug; Nuxt falls back to default.

The default layout is implicit on every other page (the majority). If a page has no layout: line, that's default.

The phantom admin layout

One page in the codebase declares layout: 'admin' but no layouts/admin.vue file exists. Nuxt silently falls back to the default layout in this case — there's no build error, only a console warning if you look. Verify with the team whether this should be a real layout or whether the declaration should be removed. If you ever see "phantom layout" diagnostics in build logs, this is the source.

What each layout provides

The contracts each layout exposes are not formalised — pages just rely on whatever the layout component renders. A few practical points:

default.vue

  • Renders the app header and sidebar (component lookups inside the layout).
  • Owns the impersonation banner (shows when impersonationLogin cookie is true).
  • Owns the welcome modal trigger.
  • Hosts the global vue-toastification and vue-snotify containers.
  • Holds the <nuxt /> content slot.
  • Reads $store.state.sidebarVisible and $store.state.userBlockVisible to drive collapse/expand.

If your page needs to suppress the sidebar without switching layouts, dispatch toggleSidebar from the page's mounted hook. This is project-specific behaviour, not a Nuxt convention.

onBoard.vue

  • Stripped chrome: typically just a logo, a step indicator, and the page content.
  • Often paired with mixins/onboardingNavigation for next/previous-step buttons.
  • Does not show the main sidebar — onboarding is a wizard, not a navigable surface.

If you write a new onboarding step, use this layout.

fourOhOne.vue

  • Minimal chrome (header logo, perhaps).
  • Doesn't load the sidebar or full chrome.
  • Used for any page that should "feel light": redirect skeletons, social-OAuth callbacks, post-checkout landings, public marketing pages.

The name is historical. Treat it as "minimal layout," not "404 layout."

someliNetwork.vue

  • Distinct visual treatment for the Someli Network section.
  • Verify with the team for what's specific to it (likely a different sidebar / nav structure tailored to community features).

specialOffer.vue

  • Marketing-page treatment: hero imagery, no-app chrome, CTA-driven layout.
  • Used for promotional flows (corporate offers, special pricing).

error.vue

  • Nuxt's error layout. Renders when a page throws or 404s.
  • Don't reuse it as a normal layout.

Layout transitions

nuxt.config.js declares:

layoutTransition: { name: 'layout', mode: 'out-in' }
pageTransition:   { name: 'page',   mode: 'out-in' }

So switching layout (e.g. moving from default to onBoard) triggers a layout-leave / layout-enter CSS animation. Keep this in mind when debugging "the page flashes briefly" issues — the transition is intentional.

Choosing a layout

A small flowchart:

Is the page authenticated app content (dashboard, planner, settings)?
  → default

Is the page an onboarding step (subjects_services, brandkit during onboarding, etc.)?
  → onBoard

Is the page a transient surface (redirect, callback, plain landing, public)?
  → fourOhOne

Is the page in the Someli Network section?
  → someliNetwork

Is the page a marketing/promotional surface?
  → specialOffer

Anything else?
  → default

When in doubt, copy the layout choice from the most similar existing page.

Adding a new layout

You'll rarely need to. If you really do:

  1. Create layouts/<name>.vue with at least a <nuxt /> slot.
  2. Use layout: '<name>' on the consuming pages.
  3. Update this doc.
  4. Update the page transition CSS if the layout introduces unique entry/exit animations.
  5. Don't name it admin until you actually finish it — there's already a phantom reference somewhere.