Everything there is to know about how config files work.

For the list of configurations, see instead:

+ files

You configure your Vike app by creating + files such as +config.js.

For example, you can set the Page and Layout settings of a page by defining +config.js:

// /pages/product/@id/+config.js
 
import Page from './Page'
import Layout from './Layout'
 
export default {
  Page,
  Layout
}
// /pages/product/@id/Page.jsx
 
export default /* ... */
// /pages/product/@id/Layout.jsx
 
export default /* ... */

For more convenience, you can also do this:

// /pages/product/@id/+config.js
 
import Page from './Page'
import Layout from './Layout'
 
export default {
  Page,
  Layout
}
// /pages/product/@id/Page.jsx
// /pages/product/@id/+Page.jsx
 
export default /* ... */
// /pages/product/@id/Layout.jsx
// /pages/product/@id/+Layout.jsx
 
export default /* ... */

Except of +config.js, any + file corresponds to a Vike setting or a Vike hook.

Inheritance

You can apply configurations to all pages, a group of pages, or only one page. For example:

pages/(marketing)/index/+Page.jsx    # URL: /
pages/(marketing)/about/+Page.jsx    # URL: /about
# Layout for marketing pages
pages/(marketing)/+Layout.jsx
 
pages/admin-panel/index/+Page.jsx    # URL: /admin-panel
pages/admin-panel/users/+Page.jsx    # URL: /admin-panel/users
# Layout for admin pages
pages/admin-panel/+Layout.jsx
 
pages/product/@id/+Page.jsx
# Layout for the product page
pages/product/@id/+Layout.jsx

The directory (marketing) is ignored by Filesystem Routing: it's used for grouping.

Where:

  • pages/(marketing)/+Layout.jsx applies to all pages living at pages/(marketing)/**
  • pages/admin-panel/+Layout.jsx applies to all pages living at pages/admin-panel/**
  • pages/product/@id/+Layout.jsx applies to one page pages/product/@id/+Page.jsx

    Technically, pages/product/@id/+Layout.jsx applies to all pages at /pages/product/@id/** but there is only one page living there.

Defaults

You can set defaults and override them. For example:

// pages/+config.js
 
export default {
  // Disable SSR by default
  ssr: false
}
// pages/(marketing)/+config.js
 
export default {
  // Enable SSR for marketing pages
  ssr: true
}

Cumulative configurations, such as <Layout>, don't get overridden. See #1692 - [Cumulative configs] New settings override and default.

Domain-driven File Structure

You can use a domain-driven file structure for better organization and for improved configuration inheritance.

Powerful

You can use config inheritance to have multiple and completely different stacks within the same app.

For example:

// pages/admin/+config.js
 
// Configuration that applies to all admin pages.
//   pages/admin/income/+Page.js
//   pages/admin/kpi/+Page.js
//   ...
 
import vue from 'vike-vue/config'
import telefunc from 'vike-telefunc/config'
 
// Vue + SPA + RPC
export default {
  ssr: false,
  extends: [vue, telefunc]
}
// pages/product/@id/+config.js
 
// Configuration that applies to the product page.
//   pages/product/@id/+Page.js
 
import react from 'vike-react/config'
import graphql from 'vike-react-apollo/config'
 
// React + SSR + GraphQL
export default {
  ssr: true,
  extends: [react, graphql]
}
// pages/(marketing)/+config.js
 
// Configuration that applies to all marketing pages.
//   pages/index/+Page.js
//   pages/about/+Page.js
//   pages/jobs/+Page.js
//   ...
 
import vue from 'vike-vue/config'
 
// Vue + SSR
export default {
  ssr: true,
  extends: [vue]
}

While it's in principle possible, there is currently a blocker for being able to use vike-vue and vike-react within the same app.

vike-telefunc doesn't exist yet: it's the upcoming integration that will enable you to use RPC for fetching initial data (instead of using +data).

Pointer imports

Internally, Vike transforms this:

// /pages/+config.js
// Environment: config
 
import Layout from '../layouts/LayoutDefault.jsx'
 
export default {
  Layout
}

Into:

// /pages/+config.js
// Environment: config
 
import Layout from '../layouts/LayoutDefault.jsx'
const Layout = 'import:../layouts/LayoutDefault.jsx:default'
 
export default {
  Layout
}

This enables Vike to load the file /pages/+config.js without having to load LayoutDefault.jsx. This means that Vike can quickly load all your +config.js files without having to load any runtime code.

These fake imports, which we call pointer imports, apply only to +config.js files. Imports in other + files are normal imports.

It's similar to when you import images:

import logo from '../images/logo.svg'
// When you import an image, you don't actually load it: you get a URL instead.
console.log(logo) // Prints: /assets/logo.svg

Vike transforms an import inside +config.js to be a pointer import if and only if the import resolves to a file that doesn't end with .js/.ts/.mjs/.mts/.cjs/.cts.

For example, an import that resolves to a .jsx or .vue file is transformed to be a pointer import:

// /pages/ssr.js
// Environment: config
 
export default false
// /pages/+config.js
// Environment: config
 
// Resolves to the file LayoutDefault.jsx (a .jsx file) => pointer import
import Layout from '../layouts/LayoutDefault'
// Resolves to the file ssr.js (a .js file) => normal import
import ssr from './ssr'
 
console.log(Layout) // Prints: import:../layouts/LayoutDefault:default
console.log(ssr) // Prints: false
 
export default {
  Layout,
  ssr
}

A .jsx or .vue file is meant to be client-/server-side runtime code (it isn't used for defining configuration logic). It therefore makes sense to treat .jsx and .vue imports as pointer imports.

Config code isn't runtime code

The config code itself is never included in runtimes:

// /pages/some-page/+config.js
 
// A CSS import in a config file doesn't have any effect. CSS should
// be imported in runtime files such as +Page.jsx instead.
import './some.css'
 
// This log is printed only when Vike loads this +config.js file (at development and when
// building your app). This log isn't included in the client nor server runtime.
// Consequently, you won't see this log in production.
console.log("I will never be logged in production")

Forbidden runtime code

If you get this error:

[Wrong Usage] title defined by /pages/+config.js must be defined over a so-called "pointer import"

Then this means you're trying to define runtime code inside a +config.js file which is forbidden.

// pages/+config.js
 
export default {
  // ❌ Forbidden: the function title() is runtime code
  title: (pageContext) => pageContext.data.title
}

The title() function is called at runtime (when the page is rendered) and not at config time (when Vike loads +config.js files).

Instead do this:

// pages/+title.js
 
// ✅ Allowed: Vike is able to lazily load this function at runtime
 
export default (pageContext) => pageContext.data.title

Or this:

// pages/+config.js
 
// ✅ Allowed: same as defining +title.js
 
import title from './title' with { type: 'pointer' }
 
export default {
  title
}

Manually mark pointer imports

You can manually mark an import to be a pointer import:

// /pages/+config.js
// Environment: config
 
import ssr from './ssr' with { type: 'pointer' }
console.log(ssr) // Prints: import:./ssr:default
🚧
The with { type: 'pointer' } import attribute isn't implement yet, see workaround at #1500.

See also