vite-plugin-ssr has been renamed Vike, see migration guide.



To make information about the authenticated user available to your pages and UI components, you usually define pageContext.user at renderPage():

// `vite-plugin-ssr` server middleware
app.get('*', async (req, res) => {
  // Authentication middlewares (e.g. Passport.js and Grant) provide information about the
  // logged-in user at req.user
  const user = req.user

  /* Or when using a third-party authentication provider (e.g. Auth0):
  const user = await authProviderApi.getUser(req.headers)

  const pageContextInit = {
    urlOriginal: req.url,
    // Make the user object available at pageContext.user
  const result = await renderPage(pageContextInit)

  /* ... */

You can then access pageContext.user from any UI component.

Login flow

By using guard() with throw redirect() or throw render() you can:

  • Implement login flows.
  • Protect private pages from unprivileged access.
// /pages/admin/index.page.route.js

import { render, redirect } from 'vite-plugin-ssr/abort'

export const guard = (pageContext) => {
  const { user } = pageContext
  if (user === null) {
    // Render the login page while preserving the URL. (This is novel technique
    // which we explain down below.)
    throw render('/login')
    /* The more traditional way, redirect the user:
    throw redirect('/login')
  if (user.role !== 'admin') {
    // Render the error page and show message to the user
    throw render(403, 'Only admins are allowed to access this page.')

Using render('/login') instead of redirect('/login') allows the URL to be preserved during the entire login flow:

  1. Unauthenticated user goes to URL /admin and sees the login page. (URL is /admin.)
  2. User fills the sign-in form and successfully logs in. (URL is still /admin.)
  3. Reload the page, the user now sees the admin page. (URL is still /admin.)

See example.

We can also define a guard() hook that applies to multiple pages:

// /pages/index.page.route.js

// We define a guard() that applies to all pages: the file lives at /pages/ and
// therefore applies to all /pages/**/*.page.js

import { render } from 'vite-plugin-ssr/abort'

export const guard = (pageContext) => {
  if (!pageContext.user) {
    throw render('/login')



Common auth tools:

In principle, we can use vite-plugin-ssr with any authentication tool. Create a new discussion on GitHub if you have questions or if you want help with integrating an authentication tool.