pageContext

The pageContext object provides contextual information about the current page.

// /pages/product/@id/+data.js
 
export async function data(pageContext) {
  // Common built-in properties
  pageContext.urlParsed.pathname // /product/42
  pageContext.routeParams.id // 42
  pageContext.headers // { cookie: 'user-id=1337', ... }
  // Common custom properties
  pageContext.user // { name: 'John', id: 1337 }
  pageContext.initialStoreState // { time: 1718872184291 }
}

The data() hook is explained at Guides > Data Fetching.

It includes:

It's accessible to all:

You can also access pageContext from the client-side by using passToClient.

Built-in

Built-in properties:

  • pageContext.Page: the export { Page } or export default of the +Page.js file.

  • pageContext.data: the value returned by the data() hook, see also API > useData().

  • pageContext.routeParams: the route parameters. (E.g. pageContext.routeParams.movieId for a page with a Route String /movie/@movieId.)

  • pageContext.urlOriginal: the current URL.

    On the server-side, pageContext.urlOriginal is the value you passed at the server middleware:

    // Server middleware
    app.get('*', async (req) => {
      const pageContextInit = {}
      // `pageContext.urlOriginal` is defined here
      pageContextInit.urlOriginal = req.url
      const pageContext = await renderPage(pageContextInit)
      /* ... */
    })

    On the client-side:

    • When using Client Routing, the value of pageContext.urlOriginal is the browser's current URL (window.location.href).
    • When using Server Routing, the value of pageContext.urlOriginal is undefined (unless you use passToClient).
  • pageContext.urlPathname: alias for pageContext.urlParsed.pathname.

  • pageContext.urlParsed: URL information:

    {
      pathname: string
      pathnameOriginal: string
      search: Record<string, string> // AKA query parameters
      searchAll: Record<string, string[]>
      searchOriginal: null | string
      hash: string
      hashOriginal: null | string
      href: string
      origin: null | string
      protocol: null | string
      hostname: null | string
      port: null | string
    }

    For example:

    https://example.com/some-base-url/hello/s%C3%A9bastien?fruit=%C3%A2pple&fruit=orânge#%C3%A2ge
    
    {
      // Without Base URL, decodes escaped characters
      pathname: '/hello/sébastien',
      // With Base URL, doesn't decode escaped characters
      pathnameOriginal: '/some-base-url/hello/s%C3%A9bastien',
      search: { fruit: 'orânge' },
      searchAll: { fruit: ['âpple', 'orânge'] },
      searchOriginal: '?fruit=%C3%A2pple&fruit=orânge',
      hash: 'âge',
      hashOriginal: '#%C3%A2ge'
      // Without Base URL, doesn't decode escaped characters
      href: 'https://example.com/hello/s%C3%A9bastien?fruit=%C3%A2pple&fruit=orânge#%C3%A2ge',
      origin: 'https://example.com',
      protocol: 'https://',
      hostname: 'example.com', // 'localhost' for http://localhost:3000
      port: null // 3000 for http://localhost:3000
    }
  • pageContext.headers: The headers of the HTTP Request. As a string object (Record<string, string>) normalized by Vike, see HTTP Headers.

  • pageContext.headersOriginal: The headers of the HTTP Request. The original object provided by the server, see HTTP Headers.

  • pageContext.config: See API > meta.

  • pageContext.isHydration: Whether the page is rendered to HTML. When using Client Routing, the value is true for the first page the user navigates to, and false for any subsequent navigation. (When using Server Routing, the value is always true.) (If the page doesn't throw an error then it's equivalent to !pageContext.isClientSideNavigation, otherwise the error page is rendered and thus pageContext.isHydration is false whereas !pageContext.isClientSideNavigation is true.)

  • pageContext.isBackwardNavigation: Whether the user is navigating back in history. The value is true when the user clicks on his browser's backward navigation button, or when invoking history.back(). The isBackwardNavigation property only works with Client Routing. (The value is always null when using Server Routing.)

  • pageContext.is404: If an error occurs, whether the error is a 404 Page Not Found or a 500 Internal Error, see API > Error page.

  • pageContext.isClientSideNavigation: Whether the page was navigated by the client-side router. In other words, when using Client Routing, the value is false for the first page the user visits, and true for any subsequent navigation. (When using Server Routing, the value is always false.)

  • pageContext.abortReason: Set by throw render() and used by the error page.

  • pageContext.abortStatusCode: Set by throw render() and used by the error page.

  • pageContext.errorWhileRendering: The first error (if there is any) that occured while rendering the page, see Guides > Error Handling.

Custom

You can define custom pageContext properties. (See TypeScript for how to define their types.)

  • At your Vike server middleware renderPage():

    app.get('*', async (req) => {
      const pageContextInit = {
        urlOriginal: req.url,
        headersOriginal: req.headers,
     
        // ***************************************
        // **** Custom pageContext properties ****
        // ***************************************
     
        // Common use case: make information about logged-in user available at pageContext.user
        user: req.user,
     
        // Or any other value:
        // pageContext.anyCustomProp
        anyCustomProp: 'some-value'
      }
      const pageContext = await renderPage(pageContextInit)
      // ...
    })

    Setting pageContext.user is a common use case for integrating authentication tools, see Guides > Authentication > Integration.

  • Using the upcoming hook onBoot() (#962). It isn't implement yet, add a comment to the GitHub issue if you need it. (We expect onBoot() to be particularly useful for pre-rendered apps.)

  • Using the onBeforeRender() hook:

    export async function onBeforeRender() {
      return {
        pageContext: {
          // ***************************************
          // **** Custom pageContext properties ****
          // ***************************************
     
          // Common use case: make the state management's initial state available.
          // pageContext.initialStoreState – initial store state
          initialStoreState: pageRendered.store.state,
     
          // pageContext.anyCustomProp
          anyCustomProp: 'some-value'
        }
      }
    }

    Setting pageContext.initialStoreState is a common use case for integrating state management tools, see Integration > Stores.

  • Using the onRenderHtml() hook:

    function onRenderHtml() {
      return {
        documentHtml: escapeInject`<html><!--...--></html>`,
        pageContext: {
          // ***************************************
          // **** Custom pageContext properties ****
          // ***************************************
          // pageContext.anyCustomProp
          anyCustomProp: 'some-value'
        }
      }
    }

TypeScript

import type {
  // For code loaded in client and server
  PageContext,
  // For code loaded in client only
  PageContextClient,
  // For code loaded in server only
  PageContextServer
} from 'vike/types'

To extend and/or refine Vike's types PageContext/PageContextServer/PageContextClient, use the global interface Vike.PageContext:

declare global {
  namespace Vike {
    interface PageContext {
      // Type of pageContext.user
      user?: {
        name: string
        id: string
        isAdmin: boolean
      }
      // Refine type of pageContext.Page (it's `unknown` by default)
      Page: () => JSX.Element
    }
  }
}
 
// If you define Vike.PageContext in a .d.ts file then
// make sure there is at least one export/import statment.
// Tell TypeScript this file isn't an ambient module:
export {}

If you use Server Routing:

import type {
  // For code loaded in client and server
  PageContextWithServerRouting as PageContext,
  // For code loaded in client only
  PageContextClientWithServerRouting as PageContextClient,
  // For code loaded in server only
  PageContextServer
} from 'vike/types'

Lifecycle

The main purpose of pageContext is to hold the information that is needed for rendering the page.

On the server-side, upon a new incoming HTTP request, a new pageContext object is created and used for rendering the HTML that is included in the HTTP response. The pageContext object is discarded after the HTML response is sent.

On the client-side, upon client-side page navigation, the pageContext object of the previous page is discarded and a new pageContext object is created.

At build-time, upon pre-rendering, a pageContext object is created for each URL and saved at dist/client/${url}/index.pageContext.json.

Vike adds information to pageContext only while rendering the page, and we recommend to treat pageContext as immutable after the rendering of the page has finished. Consequently:

  • We recommend against using pageContext to store UI state. (Use a proper state management tool instead.)
  • If you use pre-rendering, then the pageContext object of each URL is set in stone already at build-time.

See also