File-based content management system for Nuxt.js applications with powerful querying and Vue component rendering in Markdown
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Powerful query system with fluent API for filtering, sorting, and retrieving content from collections. Built on SQLite for performance with full TypeScript support and chainable methods.
Creates a chainable query builder for content collections with type-safe operations.
/**
* Creates a chainable query builder for the specified collection
* @param collection - The collection name to query
* @returns CollectionQueryBuilder instance for chaining operations
*/
function queryCollection<T>(collection: T): CollectionQueryBuilder<Collections[T]>;
interface CollectionQueryBuilder<T> {
/** Filter by exact path match */
path(path: string): CollectionQueryBuilder<T>;
/** Select specific fields from the collection items */
select<K>(...fields: K[]): CollectionQueryBuilder<Pick<T, K>>;
/** Add WHERE condition with SQL operator */
where(field: string, operator: SQLOperator, value?: unknown): CollectionQueryBuilder<T>;
/** Add AND grouped conditions */
andWhere(groupFactory: QueryGroupFunction<T>): CollectionQueryBuilder<T>;
/** Add OR grouped conditions */
orWhere(groupFactory: QueryGroupFunction<T>): CollectionQueryBuilder<T>;
/** Sort results by field in ascending or descending order */
order(field: keyof T, direction: 'ASC' | 'DESC'): CollectionQueryBuilder<T>;
/** Limit number of results returned */
limit(limit: number): CollectionQueryBuilder<T>;
/** Skip the first N results (pagination) */
skip(skip: number): CollectionQueryBuilder<T>;
/** Execute query and return all matching results */
all(): Promise<T[]>;
/** Execute query and return first result or null */
first(): Promise<T | null>;
/** Count matching results, optionally with distinct values */
count(field?: keyof T | '*', distinct?: boolean): Promise<number>;
}Usage Examples:
// Basic content retrieval
const article = await queryCollection('articles')
.path('/blog/introduction')
.first();
// Complex filtering with multiple conditions
const publishedPosts = await queryCollection('blog')
.where('published', '=', true)
.where('date', '>', '2024-01-01')
.order('date', 'DESC')
.limit(10)
.all();
// Field selection for performance
const postSummaries = await queryCollection('blog')
.select('title', 'slug', 'date', 'excerpt')
.where('featured', '=', true)
.all();
// Pagination
const page2Posts = await queryCollection('blog')
.order('date', 'DESC')
.skip(20)
.limit(10)
.all();
// Counting results
const totalPosts = await queryCollection('blog')
.where('published', '=', true)
.count();Generates hierarchical navigation trees from content collections.
/**
* Generate navigation tree from collection
* @param collection - Collection to build navigation from
* @param fields - Optional specific fields to include in navigation items
* @returns Promise resolving to navigation tree
*/
function queryCollectionNavigation<T>(
collection: T,
fields?: Array<keyof PageCollections[T]>
): ChainablePromise<T, ContentNavigationItem[]>;
interface ContentNavigationItem {
/** Display title for navigation item */
title: string;
/** URL path for navigation item */
path: string;
/** File stem (filename without extension) */
stem?: string;
/** Child navigation items */
children?: ContentNavigationItem[];
/** Whether this is a page (true) or directory (false) */
page?: boolean;
/** Additional custom fields from content */
[key: string]: unknown;
}Usage Examples:
// Generate full navigation tree
const navigation = await queryCollectionNavigation('pages');
// Include specific fields in navigation items
const navWithMeta = await queryCollectionNavigation('docs', [
'title', 'description', 'category', 'order'
]);Find content items before and after a given path for navigation (previous/next).
/**
* Find content items surrounding a given path
* @param collection - Collection to search in
* @param path - Current path to find surroundings for
* @param options - Optional configuration for surround behavior
* @returns Promise resolving to array with [previous, next] items
*/
function queryCollectionItemSurroundings<T>(
collection: T,
path: string,
opts?: SurroundOptions
): ChainablePromise<T, ContentNavigationItem[]>;
interface SurroundOptions {
/** Fields to include in surrounding items */
fields?: string[];
/** Maximum number of items to return */
limit?: number;
}Usage Examples:
// Get previous and next articles
const [prev, next] = await queryCollectionItemSurroundings(
'blog',
'/blog/current-article'
);
// Include specific fields
const surroundings = await queryCollectionItemSurroundings(
'docs',
'/docs/current-page',
{ fields: ['title', 'description', 'category'] }
);Extract searchable sections from content for building search indexes.
/**
* Extract searchable sections from collection content
* @param collection - Collection to extract sections from
* @param options - Optional configuration for section extraction
* @returns Promise resolving to searchable sections
*/
function queryCollectionSearchSections(
collection: keyof Collections,
opts?: SearchSectionOptions
): ChainablePromise<keyof Collections, SearchSection[]>;
interface SearchSectionOptions {
/** HTML tags to ignore when extracting text */
ignoredTags?: string[];
}
interface SearchSection {
/** Section identifier */
id: string;
/** Section title */
title: string;
/** Section content text */
content: string;
/** Original content path */
path: string;
/** Section hierarchy level */
level: number;
}Usage Examples:
// Extract all searchable sections
const sections = await queryCollectionSearchSections('docs');
// Ignore specific HTML tags
const cleanSections = await queryCollectionSearchSections('blog', {
ignoredTags: ['code', 'pre', 'script']
});Server-side equivalents for use in Nitro handlers and API routes.
/**
* Server-side collection querying with H3 event context
* @param event - H3 event object from Nitro handler
* @param collection - Collection to query
* @returns CollectionQueryBuilder for server-side use
*/
function queryCollection<T>(
event: H3Event,
collection: T
): CollectionQueryBuilder<Collections[T]>;
/**
* Server-side navigation generation
*/
function queryCollectionNavigation<T>(
event: H3Event,
collection: T,
fields?: Array<keyof PageCollections[T]>
): Promise<ContentNavigationItem[]>;
/**
* Server-side surround content querying
*/
function queryCollectionItemSurroundings<T>(
event: H3Event,
collection: T,
path: string,
opts?: SurroundOptions
): Promise<ContentNavigationItem[]>;
/**
* Server-side search sections querying
*/
function queryCollectionSearchSections(
event: H3Event,
collection: keyof Collections,
opts?: SearchSectionOptions
): Promise<SearchSection[]>;type SQLOperator =
| '=' | '!=' | '>' | '<' | '>=' | '<='
| 'IN' | 'NOT IN'
| 'LIKE' | 'NOT LIKE'
| 'IS NULL' | 'IS NOT NULL';
interface QueryGroupFunction<T> {
(group: CollectionQueryGroup<T>): CollectionQueryGroup<T>;
}
interface CollectionQueryGroup<T> {
where(field: string, operator: SQLOperator, value?: unknown): CollectionQueryGroup<T>;
andWhere(groupFactory: QueryGroupFunction<T>): CollectionQueryGroup<T>;
orWhere(groupFactory: QueryGroupFunction<T>): CollectionQueryGroup<T>;
}
interface ChainablePromise<T, R> extends Promise<R> {
collection: T;
}Install with Tessl CLI
npx tessl i tessl/npm-nuxt--content