The pageContext object provides contextual information about the current page.

// /pages/product/@id/+data.js
 
export async function data(pageContext) {
  // Commonly used built-in properties
  pageContext.urlParsed.pathname // /product/42
  pageContext.routeParams.id // 42
  pageContext.headers // { cookie: 'user-id=1337', ... }
  // Commonly added 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 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.previousPageContext: Upon client-side page navigation, you can use pageContext.previousPageContext to access the pageContext of the previous page. See Lifecycle.

  • 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 occurred while rendering the page, see Integration > Error Tracking.

Custom

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

  • At renderPage():

    // Your Vike server middleware integration
    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.someCustomProp
        someCustomProp: 'some-value'
      }
      const pageContext = await renderPage(pageContextInit)
      // ...
    })

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

  • At any Vike hook.

    // +someHook.js
    export function someHook(pageContext) {
      pageContext.someCustomProp = 'some-value' // Add or modify property
    }
  • At any UI component, by using usePageContext().

    // Inside a UI component
    const pageContext = usePageContext()
    pageContext.someCustomProp = 'some-value' // Add or modify property
  • At navigate({ pageContext: { someExtra: 'value' } }).

FAQ

Can I mutate pageContext?

Yes, it's a common practice to change/add pageContext properties at any time.

// Anywhere
pageContext.someProp = someValue

Can I use pageContext as a UI store?

Instead of using pageContext, we generally recommend using a proper UI state management tool such as React's useState(), Redux, Vue's ref(), Pinia, etc.

That said, there are use cases for using pageContext to store client-side state. For example to pass information from the previous page to the next during navigation.

See Lifecycle to understand whether using pageContext can make sense for your use case.

Can I check whether SSR is enabled?

On the server-side, you can tell whether SSR is enabled by checking whether pageContext.Page is set:

// +onAfterRenderHtml.js
 
export function onAfterRenderHtml(pageContext) {
  const isSSR = !!pageContext.Page
  if (isSSR) {
    // ...
  }
}

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 statement.
// 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

Server-side

On the server-side, upon an HTTP request, a new pageContext object is created. It's used for rendering the page to HTML. The pageContext object is discarded after the HTTP response is sent.

Client-side

Upon client-side page navigation, a new pageContext object is created.

You can use pageContext.previousPageContext to access the pageContext of the previous page.

Pre-rendering

If a page is pre-rendered, its initial pageContext value is determined at build-time and saved at dist/client/${url}/index.pageContext.json.

Consequently, the initial pageContext value of a pre-rendered page is set in stone at build-time.

See also