0
# Collections
1
2
Type-safe collection definition system with schema validation, custom sources, and flexible content organization. Collections define how content is structured, validated, and accessed.
3
4
## Capabilities
5
6
### Define Collection
7
8
Creates a type-safe collection definition with schema validation and configuration.
9
10
```typescript { .api }
11
/**
12
* Type-safe collection definition helper
13
* @param collection - Collection configuration object
14
* @returns Defined collection with type safety
15
*/
16
function defineCollection<T>(collection: Collection<T>): DefinedCollection<T>;
17
18
interface Collection<T> {
19
/** Collection type - 'page' for routable content, 'data' for structured data */
20
type: 'page' | 'data';
21
/** Source directory or custom source configuration */
22
source?: string | CustomCollectionSource;
23
/** Zod schema for content validation */
24
schema?: ZodSchema<T>;
25
/** Field definitions for content structure */
26
fields?: CollectionFields<T>;
27
}
28
29
interface DefinedCollection<T> {
30
name: string;
31
type: CollectionType;
32
source: ResolvedSource;
33
schema: ZodSchema<T>;
34
fields: ResolvedFields<T>;
35
}
36
```
37
38
**Usage Examples:**
39
40
```typescript
41
// content.config.ts
42
import { defineCollection, z } from '@nuxt/content/utils';
43
44
export const collections = {
45
// Page collection with routing
46
blog: defineCollection({
47
type: 'page',
48
source: 'content/blog/**/*.md',
49
schema: z.object({
50
title: z.string(),
51
description: z.string(),
52
publishedAt: z.date(),
53
author: z.object({
54
name: z.string(),
55
email: z.string().email(),
56
avatar: z.string().url().optional()
57
}),
58
tags: z.array(z.string()).default([]),
59
featured: z.boolean().default(false),
60
draft: z.boolean().default(false)
61
})
62
}),
63
64
// Data collection without routing
65
authors: defineCollection({
66
type: 'data',
67
source: 'content/data/authors.json',
68
schema: z.object({
69
id: z.string(),
70
name: z.string(),
71
bio: z.string(),
72
social: z.object({
73
twitter: z.string().optional(),
74
github: z.string().optional(),
75
website: z.string().url().optional()
76
}).optional()
77
})
78
}),
79
80
// Collection with custom source
81
products: defineCollection({
82
type: 'data',
83
source: {
84
driver: 'http',
85
url: 'https://api.example.com/products',
86
headers: {
87
'Authorization': 'Bearer ${PRODUCTS_API_TOKEN}'
88
}
89
},
90
schema: z.object({
91
id: z.number(),
92
name: z.string(),
93
price: z.number(),
94
category: z.string(),
95
inStock: z.boolean()
96
})
97
})
98
};
99
```
100
101
### Define Collection Source
102
103
Creates custom collection source configurations for external data.
104
105
```typescript { .api }
106
/**
107
* Custom collection source definition
108
* @param source - Custom source configuration
109
* @returns Resolved custom collection source
110
*/
111
function defineCollectionSource(
112
source: CustomCollectionSource
113
): ResolvedCustomCollectionSource;
114
115
interface CustomCollectionSource {
116
/** Source driver type */
117
driver: 'http' | 'database' | 'custom';
118
/** Source-specific configuration */
119
[key: string]: unknown;
120
}
121
122
interface HttpCollectionSource extends CustomCollectionSource {
123
driver: 'http';
124
/** API endpoint URL */
125
url: string;
126
/** HTTP headers for requests */
127
headers?: Record<string, string>;
128
/** Request method */
129
method?: 'GET' | 'POST';
130
/** Request body for POST requests */
131
body?: unknown;
132
/** Response transformation function */
133
transform?: (data: unknown) => unknown[];
134
}
135
136
interface DatabaseCollectionSource extends CustomCollectionSource {
137
driver: 'database';
138
/** Database connection string */
139
connectionString: string;
140
/** SQL query to fetch data */
141
query: string;
142
/** Query parameters */
143
params?: Record<string, unknown>;
144
}
145
```
146
147
**Usage Examples:**
148
149
```typescript
150
// HTTP API source
151
const apiSource = defineCollectionSource({
152
driver: 'http',
153
url: 'https://jsonplaceholder.typicode.com/posts',
154
headers: {
155
'User-Agent': 'Nuxt Content Bot'
156
},
157
transform: (data) => {
158
// Transform API response to match schema
159
return data.map(post => ({
160
id: post.id,
161
title: post.title,
162
content: post.body,
163
userId: post.userId
164
}));
165
}
166
});
167
168
// Database source
169
const dbSource = defineCollectionSource({
170
driver: 'database',
171
connectionString: process.env.DATABASE_URL,
172
query: 'SELECT * FROM articles WHERE published = true ORDER BY created_at DESC',
173
params: {}
174
});
175
```
176
177
### Content Configuration
178
179
Defines the complete content configuration with collections and global settings.
180
181
```typescript { .api }
182
/**
183
* Type-safe content configuration definition
184
* @param config - Content configuration object
185
* @returns Validated content configuration
186
*/
187
function defineContentConfig(config: ContentConfig): ContentConfig;
188
189
interface ContentConfig {
190
/** Collection definitions */
191
collections: Record<string, Collection<any>>;
192
/** Global content settings */
193
settings?: ContentSettings;
194
/** Custom transformers */
195
transformers?: ContentTransformer[];
196
}
197
198
interface ContentSettings {
199
/** Default markdown options */
200
markdown?: MarkdownOptions;
201
/** Global field defaults */
202
defaults?: Record<string, unknown>;
203
/** Content validation strictness */
204
strict?: boolean;
205
}
206
```
207
208
**Usage Examples:**
209
210
```typescript
211
// content.config.ts
212
export default defineContentConfig({
213
collections: {
214
blog: defineCollection({
215
type: 'page',
216
schema: z.object({
217
title: z.string(),
218
date: z.date(),
219
content: z.string()
220
})
221
}),
222
223
pages: defineCollection({
224
type: 'page',
225
source: 'content/pages/**/*.md'
226
})
227
},
228
229
settings: {
230
markdown: {
231
anchorLinks: true,
232
codeHighlight: true,
233
toc: { depth: 3 }
234
},
235
defaults: {
236
author: 'Site Admin',
237
publishedAt: new Date()
238
},
239
strict: true
240
},
241
242
transformers: [
243
// Custom content transformer
244
{
245
name: 'reading-time',
246
transform: (content) => {
247
const wordCount = content.body.split(/\s+/).length;
248
const readingTime = Math.ceil(wordCount / 200);
249
return {
250
...content,
251
readingTime: `${readingTime} min read`
252
};
253
}
254
}
255
]
256
});
257
```
258
259
### Load Content Configuration
260
261
Build-time utility for loading and resolving content configuration.
262
263
```typescript { .api }
264
/**
265
* Loads and resolves content configuration at build time
266
* @param nuxt - Nuxt instance
267
* @returns Promise resolving to loaded configuration
268
*/
269
function loadContentConfig(nuxt: Nuxt): Promise<LoadedContentConfig>;
270
271
interface LoadedContentConfig {
272
/** Resolved collection definitions */
273
collections: ResolvedCollection[];
274
/** Resolved global settings */
275
settings: ResolvedContentSettings;
276
/** Loaded transformers */
277
transformers: ContentTransformer[];
278
}
279
280
interface ResolvedCollection {
281
/** Collection name */
282
name: string;
283
/** Collection type */
284
type: CollectionType;
285
/** Resolved source configuration */
286
source: ResolvedSource;
287
/** Compiled schema */
288
schema: CompiledSchema;
289
/** Database table name */
290
table: string;
291
}
292
```
293
294
### Database Table Names
295
296
Utility for generating consistent database table names from collection names.
297
298
```typescript { .api }
299
/**
300
* Generates database table name from collection name
301
* @param name - Collection name
302
* @returns Database table name
303
*/
304
function getTableName(name: string): string;
305
```
306
307
**Usage Examples:**
308
309
```typescript
310
// Generate table names
311
const blogTable = getTableName('blog'); // 'content_blog'
312
const userProfilesTable = getTableName('userProfiles'); // 'content_user_profiles'
313
const apiDataTable = getTableName('api-data'); // 'content_api_data'
314
```
315
316
## Schema Validation
317
318
### Built-in Schemas
319
320
Pre-defined schemas for common content types and metadata.
321
322
```typescript { .api }
323
/** Pre-defined schema for content metadata */
324
const metaSchema: ZodSchema<ContentMeta>;
325
326
/** Pre-defined schema for page-type content */
327
const pageSchema: ZodSchema<PageContent>;
328
329
interface ContentMeta {
330
title?: string;
331
description?: string;
332
image?: string;
333
keywords?: string[];
334
author?: string;
335
publishedAt?: Date;
336
updatedAt?: Date;
337
}
338
339
interface PageContent extends ContentMeta {
340
slug: string;
341
path: string;
342
draft?: boolean;
343
layout?: string;
344
}
345
```
346
347
**Usage Examples:**
348
349
```typescript
350
import { metaSchema, pageSchema, z } from '@nuxt/content/utils';
351
352
// Extend built-in schemas
353
const blogSchema = pageSchema.extend({
354
category: z.string(),
355
tags: z.array(z.string()).default([]),
356
featured: z.boolean().default(false),
357
excerpt: z.string().optional()
358
});
359
360
// Use meta schema for data collections
361
const authorSchema = metaSchema.extend({
362
id: z.string(),
363
bio: z.string(),
364
social: z.object({
365
twitter: z.string().optional(),
366
github: z.string().optional()
367
}).optional()
368
});
369
```
370
371
### Content Transformers
372
373
Define custom content transformers for processing content files during build time.
374
375
```typescript { .api }
376
/**
377
* Defines a custom content transformer
378
* @param transformer - Content transformer configuration
379
* @returns Content transformer for use in collections
380
*/
381
function defineTransformer(transformer: ContentTransformer): ContentTransformer;
382
```
383
384
**Usage Examples:**
385
386
```typescript
387
import { defineTransformer } from '@nuxt/content/utils';
388
389
// Define a custom transformer for processing YAML frontmatter
390
const yamlTransformer = defineTransformer({
391
name: 'yaml-processor',
392
extensions: ['.md', '.mdx'],
393
parse: async (file) => {
394
// Custom parsing logic
395
const processed = await processYamlFrontmatter(file.body);
396
return {
397
...file,
398
body: processed.content,
399
meta: processed.frontmatter
400
};
401
}
402
});
403
404
// Define a transformer that only transforms existing content
405
const linkTransformer = defineTransformer({
406
name: 'link-processor',
407
extensions: ['.md'],
408
transform: async (content) => {
409
// Transform internal links
410
const processedBody = content.body.replace(
411
/\[([^\]]+)\]\(\.\/([^)]+)\)/g,
412
'[$1](/docs/$2)'
413
);
414
return { ...content, body: processedBody };
415
}
416
});
417
```
418
419
## Types
420
421
```typescript { .api }
422
type CollectionType = 'page' | 'data';
423
424
interface PageCollection<T> {
425
type: 'page';
426
schema: ZodSchema<T>;
427
source: string | CustomCollectionSource;
428
routing?: RoutingConfig;
429
}
430
431
interface DataCollection<T> {
432
type: 'data';
433
schema: ZodSchema<T>;
434
source: string | CustomCollectionSource;
435
}
436
437
interface CollectionFields<T> {
438
[K in keyof T]?: FieldDefinition<T[K]>;
439
}
440
441
interface FieldDefinition<T> {
442
type?: string;
443
required?: boolean;
444
default?: T;
445
validate?: (value: T) => boolean | string;
446
}
447
448
interface ContentTransformer {
449
/** Transformer name */
450
name: string;
451
/** File extensions this transformer handles */
452
extensions: string[];
453
/** Parse function for handling file content */
454
parse?(file: ContentFile, options: Record<string, unknown>): Promise<TransformedContent> | TransformedContent;
455
/** Transform function for processing parsed content */
456
transform?(content: TransformedContent, options: Record<string, unknown>): Promise<TransformedContent> | TransformedContent;
457
}
458
459
interface RoutingConfig {
460
/** Dynamic route pattern */
461
pattern?: string;
462
/** Route parameters */
463
params?: Record<string, string>;
464
/** Route middleware */
465
middleware?: string[];
466
}
467
```