vike Documentation

(Replaces Next.js/Nuxt) ๐Ÿ”จ Build mission-critical applications with stability and development freedom.

RAW Doc

File: README.md

Vike

(Replaces Next.js/Nuxt) ๐Ÿ”จ Build mission-critical applications with stability and development freedom.

:eyes: What is Vike: vike.dev
:clipboard: Version history & breaking changes: CHANGELOG.md
:question: Get help: vike.dev > FAQ > How can I reach out for help?
:green_heart: Contribute: CONTRIBUTING.md

Monorepo

This is the monorepo for:

Source Output
./packages/vike/ Package vike
./packages/create-vike-core/ Package create-vike-core
./docs/ Website vike.dev

See also

Monorepo Output
github.com/vikejs/vike-react Packages vike-react, vike-react-zustand, vike-react-query, ...
github.com/vikejs/vike-vue Packages vike-vue, vike-vue-pinia, vike-vue-query, ...
github.com/vikejs/vike-solid Packages vike-solid, vike-solid-query, ...

File: docs/components/Advanced.mdx

import { Advanced } from '@brillout/docpress'

{ props.children } ๐Ÿ‘‰ We recommend using this advanced capability โ€” which can be complex โ€” only if you have a clear reason why alternatives aren't an option for you.

File: docs/components/DefaultRouting.mdx

import { Link } from '@brillout/docpress'
import { UiFrameworkExtension } from '../components'

The use Client Routing. If you don't use such Vike extension, then Vike does Server Routing by default while you can opt into Client Routing.


File: docs/components/JustAMiddleware.mdx

import { Link } from '@brillout/docpress'

From the perspective of a server, Vike is just a middleware:

ts
// server.ts

// renderPage() doesn't depend on Node.js and can be used within any JavaScript environment:
// Node.js, AWS, Cloudflare, Vercel, Deno, Bun, Lagon, ...
import { renderPage } from 'vike/server'

// Any server: Express.js, Cloudflare Worker, AWS Lambda Function, Fastify, Hono, Nitro, ...
server.addMiddleware({
  method: 'GET',
  route: '*', // catch-all
  async handler(request: Request) {
    const pageContextInit = { urlOriginal: request.url }
    const pageContext = await renderPage(pageContextInit)
    // `body` is the HTML of the page with a route matching pageContextInit.urlOriginal
    const { body, statusCode, headers } = pageContext.httpResponse
    const response = { body, statusCode, headers }
    return response
  }
})

You can embed {(() => {const content = renderPage(); return props.noLink ? content : {content} })()} into any server and any deployment environment.

Alternatively, instead of using renderPage(), you can pre-render your pages and remove the need for a production server (and deploy to a static host instead).


File: docs/components/OnlyHtmlNote.mdx

import { Link } from '@brillout/docpress'

It only generates <head> tags while rendering the HTML of the first page the user visits: the <head> tags aren't updated upon client-side page navigation. The reason is that it's only meant for HTML crawlers (most notably search engine bots), see explanation at .


File: docs/pages/abort/+Page.mdx

import { Link } from '@brillout/docpress'

You can use throw render() or throw redirect() in order to abort rendering the current page and render something else instead.

`throw redirect()` VS `throw render()` VS `navigate()`

throw redirect() VS throw render()

While throw redirect() changes the URL, throw render() preserves it:

  • If a user goes to /admin and throw redirect('/login') is called, then the /login page is rendered and the user sees a new URL /login in the address bar of his browser.
  • If a user goes to /admin and throw render('/login') is called, then the /login page is rendered but the user keeps seeing the same URL /admin in the address bar of his browser (even though the /login page is rendered).

We usually recommend using throw render() instead of throw redirect() as it preserves the URL and, therefore, the user's intention. We further explain this technique at .

throw redirect() VS navigate()

Difference between throw redirect() and navigate():

  • navigate() only works on the client-side and shouldn't be called during the rendering of a page.
  • throw redirect() works on both client- and server-side but only works during the rendering a page.

In a nutshell: if you want to abort the rendering of a page then use throw redirect(), otherwise use navigate().

For example:

  • For redirecting the user upon a form submit action, use navigate(). (Since the page is already rendered and thus throw redirect() doesn't make sense as there is no pending page rendering to abort.)
  • For protecting a page from unprivileged access, such as a normal user trying to access an admin page, use throw redirect() in order to abort (on both server- and client-side) the rendering of the admin page and redirect the user to another page instead (for example the login page).

Debug

If throw redirect() or throw render() doesn't work:

  • Make sure throw redirect() / throw render() isn't intercepted.
    In development, check your server logs for the following log. If this log is missing then it means that Vike didn't catch the throw redirect() / throw render() exception: some other code is intercepting it and thus prevents Vike from catching it.
    text
    10:00:00 AM [vike][request(42)] throw redirect('/some-url') intercepted while
    rendering /some-other-url

    Most notably, using throw redirect() / throw render() inside a UI component usually doesn't work because most UI frameworks intercept the exception, and thus Vike doesn't catch it. Instead, consider using throw redirect() / throw render() in a Vike hook such as guard() or data(), or use navigate().

  • Make sure to use throw redirect() / throw render() within a Vike hook.
    If you use throw redirect() / throw render() outside of Vike hooks, for example in some server middleware code, then Vike won't be able to intercept it.

If throw redirect() doesn't work:

  • Make sure to add pageContext.httpResponse.headers to the HTTP response.
    If you've embedded Vike into your server using renderPage(), inspect whether pageContext.httpResponse.headers contains the Location header and then double check whether you're correctly adding pageContext.httpResponse.headers to the HTTP response.

See also


import { RepoLink } from '@brillout/docpress'
import { Link } from '@brillout/docpress'

What are active links? It's the practice of visually highlighting the current page in the navigation.
For example, this page named "Active Links" is highlighted with a gray background in the navigation on the left of this website.
The link is said to be "active".

To implement active links:

  • Create a new component <Link>.
  • <Link> uses usePageContext() to access pageContext.urlPathname.
  • <Link> checks whether const isActive = href === pageContext.urlPathname and sets a CSS class accordingly <a class="is-active">.

Examples:

  • React:
  • Vue:

You cannot use window.location.pathname if you use SSR, because it isn't available when the page is rendered on the server-side.
If you have set ssr: false, then you can use window.location.pathname instead of pageContext.urlPathname.


File: docs/pages/add/+Page.mdx

import { Link, RepoLink } from '@brillout/docpress'
import { UiFrameworkExtension } from '../../components'

The following shows how to add SSR / pre-rendering (aka SSG) to an existing Vite app:

It showcases how to do so in a step-by-step, progressive, and customizable fashion:

  • Choose between SSR and pre-rendering (SSG).
  • With or without .
  • With Server Routing or Client Routing.
  • Progressively migrate towards the stack you (eventually) want.

You can choose whether you want to migrate towards a full-fledged SSR/SSG framework DX (like Next.js and Nuxt by using ), or add a minimal SSR/SSG implementation (applying a minimal amount of changes to your existing code), or something in-between.

This way, you can move quickly while progressively choosing your stack as you go.

On a high-level, this is how you add Vike to your existing Vite app:

  1. Add Vike to your vite.config.js.

    • Example:
  2. Use Vike's CLI instead of Vite's CLI.

    json5
    // package.json
    {
      "scripts": {
        "dev": "vite", // [!code --]
        "dev": "vike dev", // [!code ++]
        "build": "vite build", // [!code --]
        "build": "vike build", // [!code ++]
        "preview": "vite preview", // [!code --]
        "preview": "vike preview", // [!code ++]
      }
    }
  3. Either:

    • Enable pre-rendering, or

      See

    • add a Express.js/Hono/Fastify/... server (or add Vike's server middleware if you already have one).

      Example:

  4. Either:

    • Use , or
    • define +onRenderClient.js and +onRenderHtml.js.

      Examples:

      • {/* [MDX-workaround-list-at-end-of-note] */ }
  5. Create your first +Page.js file.

    Examples:

    • {/* [MDX-workaround-list-at-end-of-note] */ }

See also