+guard() hook
The guard() hook enables you to protect pages from unauthorized access.
// /pages/admin/+guard.js
export { guard }
import { render } from 'vike/abort'
// This guard() hook protects all pages /pages/admin/**/+Page.js
async function guard(pageContext) {
if (!pageContext.user.isAdmin) {
throw render(401, "You aren't allowed to access this page.")
}
}// /pages/admin/+guard.ts
export { guard }
import type { PageContextServer } from 'vike/types'
import { render } from 'vike/abort'
// This guard() hook protects all pages /pages/admin/**/+Page.ts
async function guard(pageContext: PageContextServer) {
if (!pageContext.user.isAdmin) {
throw render(401, "You aren't allowed to access this page.")
}
}Note that:
- It can be asynchronous. (Unlike Route Functions which are always synchronous.)
- A single
guard()hook can apply to one or multiple pages. - It's always used together with
throw render()orthrow redirect(). (Theguard()hook doesn't return any value.)
Execution order
By default, the guard() hook is the first hook called after the routing is evaluated. Most notably, it's always called before the data() hook. See API > Hooks > Lifecycle.
This guarantees that
throw render()/throw redirect()is called before fetching data. (Unauthorized data fetching can be problematic.)
If you want to guard your pages after or during fetching data, then use throw render() / throw redirect() inside your data() hook instead (or any another Vike hook).
For being able to use
throw render()/throw redirect()inside UI components, see #1707: Usethrow render()/throw redirect()inside React/Vue/Solid components.
For more control on where and when your guarding logic is executed, consider using
throw render()/throw redirect()inside another hook thanguard().
Environment
The guard() hook is called in the same environment as data(). In other words, it's always called on the server-side unless you configure data() to run on the client-side.
If the page doesn't have a data() hook, then guard() executes in the environment where routing happens. See API > Hooks > Lifecycle.
By default, the
guard()hook (and the entire+guard.jsfile) is always loaded in both the client and server — even if it executes only on the client- or server-side.
+guard.server.js
If you define +guard.server.js then it's executed and loaded only on the server.
+guard.client.js
If you define +guard.client.js then it's executed and loaded only on the client.
Usually, the motivation for defining
+guard.client.jsis to implement authorization for an SSG app that doesn't have any server. But keep in mind that+guard.client.jscannot prevent a page from being pre-rendered to HTML — pre-rendering happens at build-time while authorization is done at request-time.
Upon the first page the user visits, +guard.client.js is called before rendering/hydrating. If that's an issue, consider:
- Setting
+ssr: false. (The+guard.client.jswill then be able to block rendering.) - Using
throw render()/throw redirect()inside another hook, for example+onHydrationEnd.
Aborting hydration works with React but not with Vue.