ProGuide

Content

Learn how to build your app with @nuxt/content module.

When building a landing page, a documentation, a blog or even a changelog you will need to manage content. You can do it manually by creating a new page for each content, fetch it from a CMS, store in your own database, etc. or use the @nuxt/content module to manage your content with Git.

Setup

To get started, you can follow the Installation guide or in summary:

pnpm i @nuxt/content

Then add the module to your nuxt.config.ts:

nuxt.config.ts
export default defineNuxtConfig({
  extends: ['@nuxt/ui-pro'],
  modules: [
    '@nuxt/content',
    '@nuxt/ui'
  ]
})
You need to register @nuxt/content before @nuxt/ui otherwise Tailwind CSS classes won't be parsed in your .md and .yml files.

Now that @nuxt/content module is installed, the layer will automatically configure the syntax highlight theme with material-theme and preload some languages so you don't have to.

Typography

Some Docs and Prose components to use in your Markdown files with the MDC syntax will be automatically imported.

Utils

Some utils will be auto-imported to make the bridge between @nuxt/content and @nuxt/ui-pro:

mapContentNavigation

This util will map the navigation from fetchContentNavigation that you'll usually fetch in your app.vue file and transform it recursively into an array of objects expected by components like NavigationTree.

app.vue
<script setup lang="ts">
const { data: navigation } = await useAsyncData('navigation', () => fetchContentNavigation())
</script>

<template>
  <UHeader>
    <template #panel>
      <UNavigationTree :links="mapContentNavigation(navigation)" />
    </template>
  </UHeader>
</template>

findPageHeadline

This util will allow you to bind an headline in the PageHeader based on the page _dir.

pages/[...slug].vue
<script setup lang="ts">
const route = useRoute()

const { data: page } = await useAsyncData(route.path, () => queryContent(route.path).findOne())

const headline = computed(() => findPageHeadline(page.value))
</script>

<template>
  <UPage>
    <UPageHeader v-bind="page" :headline="headline" />
  </UPage>
</template>

findPageBreadcrumb

This util will recursively find the breadcrumb of a page based on the navigation so you can use it in the PageHeader #headline slot.

pages/[...slug].vue
<script setup lang="ts">
import type { NavItem } from '@nuxt/content/dist/runtime/types'

const navigation = inject<Ref<NavItem[]>>('navigation')

const route = useRoute()

const { data: page } = await useAsyncData(route.path, () => queryContent(route.path).findOne())

const breadcrumb = computed(() => findPageBreadcrumb(navigation.value, page.value))
</script>

<template>
  <UPage>
    <UPageHeader v-bind="page">
      <template #headline>
        <NuxtLink v-for="(link, index) in breadcrumb" :key="index" :to="link._path" :class="[index < breadcrumb.length - 1 && 'text-gray-500 dark:text-gray-400']" class="flex items-center gap-1.5 group">
          <span :class="[index < breadcrumb.length - 1 && 'group-hover:text-gray-700 dark:group-hover:text-gray-200']">{{ link.title }}</span>

          <UIcon v-if="index < breadcrumb.length - 1" name="i-heroicons-chevron-right" class="w-4 h-4" />
        </NuxtLink>
      </template>
    </UPageHeader>
  </UPage>
</template>
The Breadcrumb component will soon be available in @nuxt/ui so it will be even simpler!

Usage

We'll take some real-life examples to demonstrate the integration between @nuxt/content and @nuxt/ui-pro. Assuming that you've already setup the Structure of your app, we'll start with an app.vue file.