The Document-driven development mode gives a lot more power to Markdown-based websites.

This mode creates a direct binding between the content/ directory and pages.

It also offers page, navigation, surround and globals variables.

Enable the mode

Existing project

Add the documentDriven option in the nuxt.config:

export default defineNuxtConfig({  modules: ['@nuxt/content'],  content: {    documentDriven: true  }})

Fresh project

Start a new project with the document-driven mode enabled:

npx nuxi init doc-driven-app -t doc-driven
pnpm dlx nuxi init doc-driven-app -t doc-driven

You can also use an object to configure the behavior of the mode, checkout the configuration section.

Catch-all page

The document driven mode ships a pre-configured catch-all route.

This injected Vue page is useful for having a minimal project structure:


It comes with a direct binding between your page's meta data to the OpenGraph tags using the useContentHead() composable, providing effective SEO with no configuration.

Page slots

The page comes with 2 slot components that you can replace at your project level.

To do so, you only have to create a component with the same name in your project components/ directory.

  • <DocumentDrivenNotFound />
<template>  <h1>Page not found</h1></template>
  • <DocumentDrivenEmpty />

This component will be shown when there is no content for the current page, but the page exists.

<template>  <h1>This page is empty</h1></template>

This component will be shown when no page has been found for the current URL.

Layout binding

As the page data is available beforehand, the layout can be defined in the page front-matter:

---layout: article---This page will use the article layout!

By default, it uses the default layout if none is specified.

If you want to use another layout by default, use the layoutFallbacks option in the nuxt.config:

export default defineNuxtConfig({  content: {    documentDriven: {      layoutFallbacks: ['theme'],    }  }})

This option will search for a theme key in globals, then search for a layout key inside that object. If found, that layout key will be used as a fallback.

Global variables

Queries are being made from a route middleware and are resolved before your page renders.

This gives access to the useContent() composable anywhere in your app with the following variables:

  • page
  • surround
  • navigation
  • globals
<script setup lang="ts">const { navigation, page, surround, globals } = useContent()console.log(page.value)</script>

Extend global variables

This mode gives you a convenient way to access file data globally in your application.

Use the documentDriven.globals key of in your nuxt.config to specify a query:

export default defineNuxtConfig({  content: {    documentDriven: {      globals: {        theme: {          where: [            {              _id: 'content:_theme.yml'            }          ],          without: ['_']        }      }    }  }})

This configuration will search for a _theme.yml file in the content/ directory.

If found, a theme object will be accessible via useContent().globals:

const { theme } = useContent().globals

Any changes to these files will be automatically reflected in the application during development.

Disable or control the page data

Using special documentDriven meta in your pages, you can disable this feature for specific route or control it's behavior.

Disable document driven

Setting documentDriven to false will disable document driven. This means that exposed refs from useContent() will be undefined.

<script setup lang="ts">definePageMeta({  documentDriven: false})</script>

Control data

To control document driven data you can pass an object to documentDriven meta key and enable/disable specific parts of it.

<script setup lang="ts">definePageMeta({  documentDriven: {    page: true, // Keep page fetching enabled    surround: false // Disable surround fetching  }})</script>

Config content

You can pass custom path/query to page and surround options to config documentDriven content.

<script setup lang="ts">definePageMeta({  documentDriven: {    // Simple Path    page: '/foo',    // Rich Query    surround: {      _path: '/foo/bar'    }  }})</script>
If you change page option and leave surround unset, surround option will use the same config and page.
<script setup lang="ts">definePageMeta({  documentDriven: {    page: {      _path: '/foo/bar'    },    // surround will use `{ _path: '/foo/bar' }`  }})</script>


Jump into the Document Driven Example to see a working example.