CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nuxt--content

File-based content management system for Nuxt.js applications with powerful querying and Vue component rendering in Markdown

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

collections.mddocs/

Collections

Type-safe collection definition system with schema validation, custom sources, and flexible content organization. Collections define how content is structured, validated, and accessed.

Capabilities

Define Collection

Creates a type-safe collection definition with schema validation and configuration.

/**
 * Type-safe collection definition helper
 * @param collection - Collection configuration object
 * @returns Defined collection with type safety
 */
function defineCollection<T>(collection: Collection<T>): DefinedCollection<T>;

interface Collection<T> {
  /** Collection type - 'page' for routable content, 'data' for structured data */
  type: 'page' | 'data';
  /** Source directory or custom source configuration */
  source?: string | CustomCollectionSource;
  /** Zod schema for content validation */
  schema?: ZodSchema<T>;
  /** Field definitions for content structure */
  fields?: CollectionFields<T>;
}

interface DefinedCollection<T> {
  name: string;
  type: CollectionType;
  source: ResolvedSource;
  schema: ZodSchema<T>;
  fields: ResolvedFields<T>;
}

Usage Examples:

// content.config.ts
import { defineCollection, z } from '@nuxt/content/utils';

export const collections = {
  // Page collection with routing
  blog: defineCollection({
    type: 'page',
    source: 'content/blog/**/*.md',
    schema: z.object({
      title: z.string(),
      description: z.string(),
      publishedAt: z.date(),
      author: z.object({
        name: z.string(),
        email: z.string().email(),
        avatar: z.string().url().optional()
      }),
      tags: z.array(z.string()).default([]),
      featured: z.boolean().default(false),
      draft: z.boolean().default(false)
    })
  }),

  // Data collection without routing
  authors: defineCollection({
    type: 'data',
    source: 'content/data/authors.json',
    schema: z.object({
      id: z.string(),
      name: z.string(),
      bio: z.string(),
      social: z.object({
        twitter: z.string().optional(),
        github: z.string().optional(),
        website: z.string().url().optional()
      }).optional()
    })
  }),

  // Collection with custom source
  products: defineCollection({
    type: 'data',
    source: {
      driver: 'http',
      url: 'https://api.example.com/products',
      headers: {
        'Authorization': 'Bearer ${PRODUCTS_API_TOKEN}'
      }
    },
    schema: z.object({
      id: z.number(),
      name: z.string(),
      price: z.number(),
      category: z.string(),
      inStock: z.boolean()
    })
  })
};

Define Collection Source

Creates custom collection source configurations for external data.

/**
 * Custom collection source definition
 * @param source - Custom source configuration
 * @returns Resolved custom collection source
 */
function defineCollectionSource(
  source: CustomCollectionSource
): ResolvedCustomCollectionSource;

interface CustomCollectionSource {
  /** Source driver type */
  driver: 'http' | 'database' | 'custom';
  /** Source-specific configuration */
  [key: string]: unknown;
}

interface HttpCollectionSource extends CustomCollectionSource {
  driver: 'http';
  /** API endpoint URL */
  url: string;
  /** HTTP headers for requests */
  headers?: Record<string, string>;
  /** Request method */
  method?: 'GET' | 'POST';
  /** Request body for POST requests */
  body?: unknown;
  /** Response transformation function */
  transform?: (data: unknown) => unknown[];
}

interface DatabaseCollectionSource extends CustomCollectionSource {
  driver: 'database';
  /** Database connection string */
  connectionString: string;
  /** SQL query to fetch data */
  query: string;
  /** Query parameters */
  params?: Record<string, unknown>;
}

Usage Examples:

// HTTP API source
const apiSource = defineCollectionSource({
  driver: 'http',
  url: 'https://jsonplaceholder.typicode.com/posts',
  headers: {
    'User-Agent': 'Nuxt Content Bot'
  },
  transform: (data) => {
    // Transform API response to match schema
    return data.map(post => ({
      id: post.id,
      title: post.title,
      content: post.body,
      userId: post.userId
    }));
  }
});

// Database source
const dbSource = defineCollectionSource({
  driver: 'database',
  connectionString: process.env.DATABASE_URL,
  query: 'SELECT * FROM articles WHERE published = true ORDER BY created_at DESC',
  params: {}
});

Content Configuration

Defines the complete content configuration with collections and global settings.

/**
 * Type-safe content configuration definition
 * @param config - Content configuration object
 * @returns Validated content configuration
 */
function defineContentConfig(config: ContentConfig): ContentConfig;

interface ContentConfig {
  /** Collection definitions */
  collections: Record<string, Collection<any>>;
  /** Global content settings */
  settings?: ContentSettings;
  /** Custom transformers */
  transformers?: ContentTransformer[];
}

interface ContentSettings {
  /** Default markdown options */
  markdown?: MarkdownOptions;
  /** Global field defaults */
  defaults?: Record<string, unknown>;
  /** Content validation strictness */
  strict?: boolean;
}

Usage Examples:

// content.config.ts
export default defineContentConfig({
  collections: {
    blog: defineCollection({
      type: 'page',
      schema: z.object({
        title: z.string(),
        date: z.date(),
        content: z.string()
      })
    }),
    
    pages: defineCollection({
      type: 'page',
      source: 'content/pages/**/*.md'
    })
  },
  
  settings: {
    markdown: {
      anchorLinks: true,
      codeHighlight: true,
      toc: { depth: 3 }
    },
    defaults: {
      author: 'Site Admin',
      publishedAt: new Date()
    },
    strict: true
  },
  
  transformers: [
    // Custom content transformer
    {
      name: 'reading-time',
      transform: (content) => {
        const wordCount = content.body.split(/\s+/).length;
        const readingTime = Math.ceil(wordCount / 200);
        return {
          ...content,
          readingTime: `${readingTime} min read`
        };
      }
    }
  ]
});

Load Content Configuration

Build-time utility for loading and resolving content configuration.

/**
 * Loads and resolves content configuration at build time
 * @param nuxt - Nuxt instance
 * @returns Promise resolving to loaded configuration
 */
function loadContentConfig(nuxt: Nuxt): Promise<LoadedContentConfig>;

interface LoadedContentConfig {
  /** Resolved collection definitions */
  collections: ResolvedCollection[];
  /** Resolved global settings */
  settings: ResolvedContentSettings;
  /** Loaded transformers */
  transformers: ContentTransformer[];
}

interface ResolvedCollection {
  /** Collection name */
  name: string;
  /** Collection type */
  type: CollectionType;
  /** Resolved source configuration */
  source: ResolvedSource;
  /** Compiled schema */
  schema: CompiledSchema;
  /** Database table name */
  table: string;
}

Database Table Names

Utility for generating consistent database table names from collection names.

/**
 * Generates database table name from collection name
 * @param name - Collection name
 * @returns Database table name
 */
function getTableName(name: string): string;

Usage Examples:

// Generate table names
const blogTable = getTableName('blog'); // 'content_blog'
const userProfilesTable = getTableName('userProfiles'); // 'content_user_profiles'
const apiDataTable = getTableName('api-data'); // 'content_api_data'

Schema Validation

Built-in Schemas

Pre-defined schemas for common content types and metadata.

/** Pre-defined schema for content metadata */
const metaSchema: ZodSchema<ContentMeta>;

/** Pre-defined schema for page-type content */
const pageSchema: ZodSchema<PageContent>;

interface ContentMeta {
  title?: string;
  description?: string;
  image?: string;
  keywords?: string[];
  author?: string;
  publishedAt?: Date;
  updatedAt?: Date;
}

interface PageContent extends ContentMeta {
  slug: string;
  path: string;
  draft?: boolean;
  layout?: string;
}

Usage Examples:

import { metaSchema, pageSchema, z } from '@nuxt/content/utils';

// Extend built-in schemas
const blogSchema = pageSchema.extend({
  category: z.string(),
  tags: z.array(z.string()).default([]),
  featured: z.boolean().default(false),
  excerpt: z.string().optional()
});

// Use meta schema for data collections
const authorSchema = metaSchema.extend({
  id: z.string(),
  bio: z.string(),
  social: z.object({
    twitter: z.string().optional(),
    github: z.string().optional()
  }).optional()
});

Content Transformers

Define custom content transformers for processing content files during build time.

/**
 * Defines a custom content transformer
 * @param transformer - Content transformer configuration
 * @returns Content transformer for use in collections
 */
function defineTransformer(transformer: ContentTransformer): ContentTransformer;

Usage Examples:

import { defineTransformer } from '@nuxt/content/utils';

// Define a custom transformer for processing YAML frontmatter
const yamlTransformer = defineTransformer({
  name: 'yaml-processor', 
  extensions: ['.md', '.mdx'],
  parse: async (file) => {
    // Custom parsing logic
    const processed = await processYamlFrontmatter(file.body);
    return {
      ...file,
      body: processed.content,
      meta: processed.frontmatter
    };
  }
});

// Define a transformer that only transforms existing content
const linkTransformer = defineTransformer({
  name: 'link-processor',
  extensions: ['.md'],
  transform: async (content) => {
    // Transform internal links
    const processedBody = content.body.replace(
      /\[([^\]]+)\]\(\.\/([^)]+)\)/g,
      '[$1](/docs/$2)'
    );
    return { ...content, body: processedBody };
  }
});

Types

type CollectionType = 'page' | 'data';

interface PageCollection<T> {
  type: 'page';
  schema: ZodSchema<T>;
  source: string | CustomCollectionSource;
  routing?: RoutingConfig;
}

interface DataCollection<T> {
  type: 'data';
  schema: ZodSchema<T>;
  source: string | CustomCollectionSource;
}

interface CollectionFields<T> {
  [K in keyof T]?: FieldDefinition<T[K]>;
}

interface FieldDefinition<T> {
  type?: string;
  required?: boolean;
  default?: T;
  validate?: (value: T) => boolean | string;
}

interface ContentTransformer {
  /** Transformer name */
  name: string;
  /** File extensions this transformer handles */
  extensions: string[];
  /** Parse function for handling file content */
  parse?(file: ContentFile, options: Record<string, unknown>): Promise<TransformedContent> | TransformedContent;
  /** Transform function for processing parsed content */
  transform?(content: TransformedContent, options: Record<string, unknown>): Promise<TransformedContent> | TransformedContent;
}

interface RoutingConfig {
  /** Dynamic route pattern */
  pattern?: string;
  /** Route parameters */
  params?: Record<string, string>;
  /** Route middleware */
  middleware?: string[];
}

Install with Tessl CLI

npx tessl i tessl/npm-nuxt--content

docs

collections.md

configuration.md

index.md

navigation-utilities.md

navigation.md

preview.md

querying.md

rendering.md

runtime-utilities.md

tile.json