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

preview.mddocs/

Preview System

Live content editing system with field definitions, authentication, and real-time preview capabilities for content management workflows.

Capabilities

Field Definition

Creates preview-compatible field configurations for content editing interfaces.

/**
 * Helper to build preview-compatible field configuration
 * @param config - Field configuration object
 * @returns Configured preview field
 */
function field(config: FieldConfig): PreviewField;

interface FieldConfig {
  /** Field input type */
  type: PickerTypes;
  /** Field identifier */
  name: string;
  /** Display label for field */
  label?: string;
  /** Whether field is required */
  required?: boolean;
  /** Default value */
  default?: unknown;
  /** Field validation rules */
  validation?: ValidationRule[];
  /** Field-specific options */
  options?: FieldOptions;
}

interface PreviewField {
  type: PickerTypes;
  name: string;
  label: string;
  required: boolean;
  default?: unknown;
  validation: ValidationRule[];
  options: FieldOptions;
}

Usage Examples:

import { field } from '@nuxt/content/preview';

// Text input field
const titleField = field({
  type: 'text',
  name: 'title',
  label: 'Article Title',
  required: true,
  validation: [
    { type: 'minLength', value: 5, message: 'Title must be at least 5 characters' },
    { type: 'maxLength', value: 100, message: 'Title must not exceed 100 characters' }
  ]
});

// Rich text editor
const contentField = field({
  type: 'richtext',
  name: 'content',
  label: 'Article Content',
  required: true,
  options: {
    toolbar: ['bold', 'italic', 'link', 'code'],
    placeholder: 'Write your article content...'
  }
});

// Select dropdown
const categoryField = field({
  type: 'select',
  name: 'category',
  label: 'Category',
  required: true,
  options: {
    choices: [
      { label: 'Technology', value: 'tech' },
      { label: 'Design', value: 'design' },
      { label: 'Business', value: 'business' }
    ]
  }
});

// Date picker
const publishDateField = field({
  type: 'date',
  name: 'publishedAt',
  label: 'Publish Date',
  default: new Date(),
  options: {
    format: 'YYYY-MM-DD',
    minDate: new Date()
  }
});

Group Definition

Groups preview fields with schema validation and organization.

/**
 * Groups preview fields with schema validation
 * @param config - Group configuration object
 * @returns Configured preview group
 */
function group(config: GroupConfig): PreviewGroup;

interface GroupConfig {
  /** Group identifier */
  name: string;
  /** Display label for group */
  label?: string;
  /** Fields within this group */
  fields: PreviewField[];
  /** Group validation schema */
  schema?: PartialSchema;
  /** Group display options */
  options?: GroupOptions;
}

interface PreviewGroup {
  name: string;
  label: string;
  fields: PreviewField[];
  schema: PartialSchema;
  options: GroupOptions;
}

Usage Examples:

import { field, group } from '@nuxt/content/preview';

// Article metadata group
const metadataGroup = group({
  name: 'metadata',
  label: 'Article Metadata',
  fields: [
    field({
      type: 'text',
      name: 'title',
      label: 'Title',
      required: true
    }),
    field({
      type: 'textarea',
      name: 'description',
      label: 'Description',
      options: { rows: 3 }
    }),
    field({
      type: 'select',
      name: 'status',
      label: 'Status',
      default: 'draft',
      options: {
        choices: [
          { label: 'Draft', value: 'draft' },
          { label: 'Published', value: 'published' },
          { label: 'Archived', value: 'archived' }
        ]
      }
    })
  ],
  options: {
    collapsible: true,
    expanded: true
  }
});

// Author information group
const authorGroup = group({
  name: 'author',
  label: 'Author Information',
  fields: [
    field({
      type: 'text',
      name: 'name',
      label: 'Author Name',
      required: true
    }),
    field({
      type: 'email',
      name: 'email',
      label: 'Author Email'
    }),
    field({
      type: 'image',
      name: 'avatar',
      label: 'Author Avatar',
      options: {
        accept: 'image/*',
        maxSize: '2MB'
      }
    })
  ]
});

Field Types

Text Input Types

type TextFieldTypes = 'text' | 'textarea' | 'email' | 'url' | 'password';

interface TextFieldOptions {
  /** Placeholder text */
  placeholder?: string;
  /** Maximum character length */
  maxLength?: number;
  /** Minimum character length */
  minLength?: number;
  /** Input pattern regex */
  pattern?: string;
  /** Number of rows (textarea only) */
  rows?: number;
  /** Auto-resize textarea */
  autoResize?: boolean;
}

Rich Content Types

type RichContentTypes = 'richtext' | 'markdown' | 'code';

interface RichTextOptions {
  /** Toolbar buttons to show */
  toolbar?: string[];
  /** Editor placeholder */
  placeholder?: string;
  /** Enable code blocks */
  codeBlocks?: boolean;
  /** Custom editor extensions */
  extensions?: EditorExtension[];
}

interface MarkdownOptions {
  /** Enable live preview */
  preview?: boolean;
  /** Syntax highlighting theme */
  theme?: string;
  /** Supported languages for code blocks */
  languages?: string[];
}

interface CodeOptions {
  /** Programming language */
  language?: string;
  /** Show line numbers */
  lineNumbers?: boolean;
  /** Editor theme */
  theme?: string;
  /** Tab size */
  tabSize?: number;
}

Selection Types

type SelectionTypes = 'select' | 'multiselect' | 'radio' | 'checkbox' | 'toggle';

interface SelectionOptions {
  /** Available choices */
  choices: Choice[];
  /** Allow multiple selections */
  multiple?: boolean;
  /** Enable search/filtering */
  searchable?: boolean;
  /** Maximum selections (multiselect) */
  maxSelections?: number;
}

interface Choice {
  /** Display label */
  label: string;
  /** Option value */
  value: string | number;
  /** Option description */
  description?: string;
  /** Option disabled state */
  disabled?: boolean;
  /** Option group */
  group?: string;
}

Media Types

type MediaTypes = 'image' | 'file' | 'video' | 'audio';

interface MediaOptions {
  /** Accepted file types */
  accept?: string;
  /** Maximum file size */
  maxSize?: string;
  /** Image dimensions */
  dimensions?: {
    width?: number;
    height?: number;
    aspectRatio?: string;
  };
  /** Generate thumbnails */
  thumbnails?: boolean;
  /** Upload destination */
  destination?: string;
}

Date and Time Types

type DateTimeTypes = 'date' | 'datetime' | 'time';

interface DateTimeOptions {
  /** Date format */
  format?: string;
  /** Minimum date */
  minDate?: Date;
  /** Maximum date */
  maxDate?: Date;
  /** Enable time picker */
  enableTime?: boolean;
  /** Time format (12/24 hour) */
  timeFormat?: '12' | '24';
  /** Default timezone */
  timezone?: string;
}

Validation

Validation Rules

interface ValidationRule {
  /** Validation type */
  type: ValidationType;
  /** Validation value/parameter */
  value?: unknown;
  /** Error message */
  message: string;
  /** Custom validation function */
  validator?: (value: unknown) => boolean | Promise<boolean>;
}

type ValidationType = 
  | 'required' | 'minLength' | 'maxLength' 
  | 'min' | 'max' | 'email' | 'url' 
  | 'pattern' | 'custom';

Usage Examples:

// Complex validation rules
const emailField = field({
  type: 'email',
  name: 'email',
  label: 'Email Address',
  required: true,
  validation: [
    {
      type: 'required',
      message: 'Email is required'
    },
    {
      type: 'email',
      message: 'Must be a valid email address'
    },
    {
      type: 'custom',
      message: 'Email domain not allowed',
      validator: async (email) => {
        const domain = email.split('@')[1];
        const allowedDomains = ['company.com', 'partner.com'];
        return allowedDomains.includes(domain);
      }
    }
  ]
});

Preview Integration

Content Form Configuration

// content/blog/preview.config.ts
import { field, group } from '@nuxt/content/preview';

export default {
  // Field groups for content editing
  groups: [
    group({
      name: 'content',
      label: 'Content',
      fields: [
        field({
          type: 'text',
          name: 'title',
          label: 'Title',
          required: true
        }),
        field({
          type: 'richtext',
          name: 'content',
          label: 'Content',
          required: true
        })
      ]
    }),
    
    group({
      name: 'meta',
      label: 'Metadata',
      fields: [
        field({
          type: 'date',
          name: 'publishedAt',
          label: 'Publish Date'
        }),
        field({
          type: 'multiselect',
          name: 'tags',
          label: 'Tags',
          options: {
            choices: [
              { label: 'Vue.js', value: 'vue' },
              { label: 'Nuxt.js', value: 'nuxt' },
              { label: 'JavaScript', value: 'js' }
            ]
          }
        })
      ]
    })
  ]
};

Types

type PickerTypes = 
  | 'text' | 'textarea' | 'email' | 'url' | 'password'
  | 'richtext' | 'markdown' | 'code'
  | 'select' | 'multiselect' | 'radio' | 'checkbox' | 'toggle'
  | 'image' | 'file' | 'video' | 'audio'
  | 'date' | 'datetime' | 'time'
  | 'number' | 'range' | 'color';

interface PreviewFieldData {
  /** Field type */
  type: PickerTypes;
  /** Field value */
  value: unknown;
  /** Field metadata */
  meta: FieldMeta;
  /** Validation state */
  validation: ValidationState;
}

interface ConfigInputsTypes {
  [fieldName: string]: PickerTypes;
}

interface PartialSchema {
  /** Schema validation function */
  validate: (data: unknown) => ValidationResult;
  /** Schema transformation function */
  transform?: (data: unknown) => unknown;
}

interface GroupOptions {
  /** Group is collapsible */
  collapsible?: boolean;
  /** Group is expanded by default */
  expanded?: boolean;
  /** Group display order */
  order?: number;
  /** Group CSS classes */
  className?: string;
  /** Group conditional display */
  conditional?: ConditionalRule;
}

interface ConditionalRule {
  /** Field to watch for condition */
  field: string;
  /** Condition operator */
  operator: '=' | '!=' | 'in' | 'not_in';
  /** Condition value */
  value: unknown;
}

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