The Nuxt Content module automatically parses any content files within the content/ directory located at the root of your Nuxt application. This setup allows you to freely structure the folder to suit your project's needs.
For better organization, consider using Content Collections, which let you categorize and manage content more effectively. These collections are defined in a content.config.ts file.
content.config.ts file is present, all files within the content folder are parsed and imported by default. However, once a config file is added, only files matching the specified path patterns defined in collections will be imported.Content Collections organize related items within your Nuxt Content project. They provide a structured way to manage your content, making it easier to query, display, and maintain your site's data.
Key features include:
Create a content.config.ts file in your project's root directory. This special file configures your collections database, utility types, and content handling.
Here's a basic example:
import { defineCollection, defineContentConfig } from '@nuxt/content'
export default defineContentConfig({
collections: {
docs: defineCollection({
// Specify the type of content in this collection
type: 'page',
// Load every file inside the `content` directory
source: '**',
})
}
})
exclude attribute to explicitly exclude a document from other collections using appropriate regex patterns.This topic is still under discussion in this issue: nuxt/content#2966.Schemas enforce data consistency within a collection and serve as the source of truth for TypeScript types.
On top of the built-in fields, you can define a schema by adding the schema property to your collection by using a zod schema:
import { defineCollection, defineContentConfig } from '@nuxt/content'
import { z } from 'zod'
export default defineContentConfig({
collections: {
blog: defineCollection({
type: 'page',
source: 'blog/*.md',
// Define custom schema for docs collection
schema: z.object({
tags: z.array(z.string()),
image: z.string(),
date: z.date()
})
})
}
})
@nuxt/content exposes a z object that contains a set of Zod schemas for common data types. Check Zod’s README for complete documentation on how Zod works and what features are available.Optimize query performance by defining indexes on collection columns. Indexes are especially useful for fields used in filtering, sorting, or lookups.
import { defineCollection, defineContentConfig } from '@nuxt/content'
import { z } from 'zod'
export default defineContentConfig({
collections: {
products: defineCollection({
type: 'data',
source: 'products/*.json',
schema: z.object({
sku: z.string(),
price: z.number(),
category: z.string(),
inStock: z.boolean(),
}),
indexes: [
// Single column indexes
{ columns: ['category'] },
{ columns: ['price'] },
// Composite index for category + price filtering
{ columns: ['category', 'price'] },
// Unique index to ensure SKU uniqueness
{ columns: ['sku'], unique: true },
// Custom index name (optional)
{ columns: ['inStock', 'category'], name: 'idx_stock_category' },
],
}),
},
})
WHERE clause on an indexed column counts as only 1 row read when there's a single match. Without an index, D1 counts all rows scanned in the table, significantly increasing your read costs. Indexes can dramatically reduce your D1 billing.Index Configuration Options:
columns (required): Array of column names to include in the indexunique (optional): Set to true to create a unique index (default: false)name (optional): Custom index name. If omitted, auto-generates as idx_{collection}_{column1}_{column2}Performance Tips:
where() queries for faster filteringsort() for optimized sortingUse the queryCollection util to fetch one or all items from a collection:
<script setup lang="ts">
const { data: posts } = await useAsyncData('blog', () => queryCollection('blog').all())
</script>
<template>
<div>
<h1>Blog</h1>
<ul>
<li v-for="post in posts" :key="post.id">
<NuxtLink :to="post.path">{{ post.title }}</NuxtLink>
</li>
</ul>
</div>
</template>
The defineCollection function defines a collection in your content configuration. Here's its TypeScript signature:
function defineCollection(collection: Collection): DefinedCollection
type Collection = {
// Determines how content is processed
type: 'page' | 'data'
// Specifies content location
source?: string | CollectionSource
// Zod schema for content validation and typing
schema?: ZodObject<T>
// Database indexes for query optimization
indexes?: CollectionIndex[]
}
type CollectionIndex = {
// Column names to include in the index
columns: string[]
// Optional custom index name
name?: string
// Whether this is a unique index (default: false)
unique?: boolean
}
type CollectionSource = {
// Glob pattern for content matching
include: string
// .path prefix (only applies to 'page' type)
prefix?: string
// Glob patterns to exclude content
exclude?: string[]
// Root directory for content matching
cwd?: string
// Remote git repository URL (e.g., https://github.com/nuxt/content)
repository?: string
// Authentication token for private repositories (e.g., GitHub personal access token)
authToken?: string
}
The function returns the defined collection object.