---
title: "Default pages"
description: "The ready-made pages the module mounts, and the customization ladder that replaces ejecting."
canonical_url: "https://nuxt-backend.dev/docs/ui/pages"
---
# Default pages

> The ready-made pages the module mounts, and the customization ladder that replaces ejecting.

Install the module and these routes exist — no files, no config:

<table>
<thead>
  <tr>
    <th>
      Route
    </th>
    
    <th>
      Page
    </th>
    
    <th>
      Access
    </th>
    
    <th>
      Built on
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        /login
      </code>
    </td>
    
    <td>
      Passwordless sign-in (passkeys + email OTP)
    </td>
    
    <td>
      public
    </td>
    
    <td>
      <code>
        <AuthForm>
      </code>
      
       · <code>
        useLoginFlow
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        /pricing
      </code>
    </td>
    
    <td>
      Plan cards + credit packs, live from billing
    </td>
    
    <td>
      public
    </td>
    
    <td>
      <code>
        <PricingTable>
      </code>
      
       · <code>
        useBilling
      </code>
      
      , <code>
        useCredits
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        /settings
      </code>
    </td>
    
    <td>
      Workspaces, plan summary, credits
    </td>
    
    <td>
      auth
    </td>
    
    <td>
      <code>
        <WorkspaceSettings>
      </code>
      
       · <code>
        useOrganization
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        /profile
      </code>
    </td>
    
    <td>
      Identity, display name, change email
    </td>
    
    <td>
      auth
    </td>
    
    <td>
      <code>
        <ProfileSettings>
      </code>
      
       · <code>
        useAuth
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        /security
      </code>
    </td>
    
    <td>
      Passkeys, sessions, deletion
    </td>
    
    <td>
      auth
    </td>
    
    <td>
      <code>
        <SecuritySettings>
      </code>
      
       · <code>
        usePasskeys
      </code>
      
      , <code>
        useSessions
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        /accept-invitation
      </code>
    </td>
    
    <td>
      Workspace invitation accept links
    </td>
    
    <td>
      auth
    </td>
    
    <td>
      <code>
        <AcceptInvitation>
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        /oauth/consent
      </code>
    </td>
    
    <td>
      An agent's request for access, approved or denied
    </td>
    
    <td>
      auth
    </td>
    
    <td>
      <code>
        <AgentConsent>
      </code>
    </td>
  </tr>
</tbody>
</table>

Each page is a thin wrapper around one auto-imported component, styled by the
neutral `ui.css` the module adds. The `/login` path doubles as the `auth`
middleware's redirect target, and the original destination rides along as
`?redirect=` so sign-in returns the visitor where they were headed.

Every page mounts. The [`pages` module option](https://nuxt-backend.dev/docs/reference/configuration/module-options)
moves one: give its key a path. To replace a page, put an app page at its path;
the module detects it and mounts nothing there ([Replace a page](https://nuxt-backend.dev/docs/ui/customize/replace-pages)).

```ts
export default defineNuxtConfig({
  modules: ['nuxt-backend'],
  backend: {
    pages: {
      pricing: '/plans',     // the packaged pricing page, at /plans
      settings: '/account',  // the packaged settings page, at /account
    },
  },
})
```

A page key takes a path and nothing else. A `true` or `false` left from 0.1, for
one page or for the whole option, stops the build with an error that names it and
links the [Upgrade page](https://nuxt-backend.dev/docs/ship/migrate/upgrade#pages-the-stylesheet-and-the-webhook-log-are-always-on).

## Search engines

The five `auth` pages redirect a signed-out visitor to sign-in, so the module keeps them out of search indexes and sitemaps, and out of caches (see [Caches](#caches)). It adds a route rule at each one's path; the public pages get `prerender: false` alone, since no page is prerendered:

```ts
routeRules: {
  '/settings': {
    prerender: false,
    robots: false,
    sitemap: false,
    cache: false,
    swr: false,
    isr: false,
    headers: { 'cache-control': 'private, no-store' },
  },
  // …the same for /profile, /security, /accept-invitation and /oauth/consent
  '/login': { prerender: false },
  '/pricing': { prerender: false },
}
```

[`@nuxtjs/robots`](https://nuxtseo.com/docs/robots/getting-started/introduction) answers `robots: false` with a `noindex, nofollow` header and meta tag, and [`@nuxtjs/sitemap`](https://nuxtseo.com/docs/sitemap/getting-started/introduction) leaves the URL out; both come with `@nuxtjs/seo`. Without those modules the rules do nothing. `/login` and `/pricing` stay indexable, and `robots.txt` is not changed: `noindex` is the signal for a page that exists but has nothing public on it.

The rules follow the path, so an app page that shadows one of these gets them too. A rule you set for the same path wins key by key: `routeRules: { '/security': { robots: true } }` indexes that page again.

## Caches

A signed-in render carries the session's token: the server renders the page with it, and it rides in the page's payload to the browser. So the private pages turn off each cache a route rule can turn on (`cache`, `swr`, and the hosting platform's `isr`) and answer `cache-control: private, no-store`.

That holds at each page's exact path, and only there. Nitro matches route rules case-sensitively while the router matches pages case-insensitively: under an app-wide rule such as `'/**': { swr: 60 }`, `/SETTINGS` renders the settings page under the wildcard's cache rather than the page's own rule, and a cached render can reach the next visitor. A localized copy of a page (`/fr/settings`) is another path the rules do not cover. When a wildcard `swr`, `isr` or `cache` rule covers a private page, the module warns at startup.

Scope cache rules to the public pages they are meant for, never the whole app:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  routeRules: {
    '/': { swr: 3600 },
    '/blog/**': { swr: 3600 },
  },
})
```

## The customization ladder

Every page is replaceable without ejecting, one rung at a time: CSS tokens, `appConfig.backend` content, component slots, and finally your own page at the same route built on the same composables. [Customize](https://nuxt-backend.dev/docs/ui/customize) walks the five rungs.


## Sitemap

See the full [sitemap](https://nuxt-backend.dev/sitemap.md) for all pages.
