Chapter 6: Fields and Data Types
Master Vibe CMS's field system to build flexible, type-safe content schemas. This chapter provides comprehensive coverage of field types, interface options, validation, and best practices for schema design.
Understanding the Field System
Every collection in Vibe CMS is defined by its fields. Fields determine what data can be stored, how it's validated, and how content editors interact with it in the admin interface.
Each field has two critical properties:
- Field Type: The data type stored in the database (text, markdown, number, boolean, file)
- Interface Type: The UI component used for editing (input, textarea, markdown, single_file, multiple_files)
Field Types Deep Dive
text
The text field type stores string data. It's the most versatile field type, suitable for any text content from short labels to long descriptions.
Storage: PostgreSQL text column in the data JSONB field
Use Cases:
- Titles and headlines
- Names and labels
- Descriptions and summaries
- Short-form content
- URL slugs and identifiers
Validation: No length limits at the database level, but interface types may enforce constraints
Example Schema:
{
field_name: "title",
field_type: "text",
interface_type: "input", // Single-line input
is_required: true
}
Compatible Interfaces: input, textarea
markdown
The markdown field type stores markdown-formatted text, ideal for rich content that needs structure, formatting, and embedded media.
Storage: PostgreSQL text column containing markdown syntax
Use Cases:
- Blog post content
- Article bodies
- Documentation pages
- Rich descriptions with formatting
- Content requiring headings, lists, links, images
Validation: Markdown syntax is stored as-is; validation happens at render time
Example Schema:
{
field_name: "content",
field_type: "markdown",
interface_type: "markdown", // Rich markdown editor
is_required: true
}
Compatible Interfaces: markdown (only)
Note: The markdown interface typically provides a live preview, syntax highlighting, and toolbar for common formatting operations.
number
The number field type stores numeric data, including integers and floating-point values.
Storage: PostgreSQL numeric type in JSONB
Use Cases:
- Prices and monetary values
- Quantities and counts
- Ratings and scores
- Sort orders and priorities
- Statistical data
Validation: Must be a valid numeric value; additional constraints can be added at the application level
Example Schema:
{
field_name: "price",
field_type: "number",
interface_type: "input",
is_required: false
}
Compatible Interfaces: input (only)
boolean
The boolean field type stores true/false values, perfect for flags, toggles, and binary states.
Storage: PostgreSQL boolean in JSONB
Use Cases:
- Feature flags (is_featured, is_published)
- User preferences (email_notifications_enabled)
- State toggles (is_active, is_archived)
- Conditional logic (show_author, enable_comments)
Validation: Must be exactly true or false
Example Schema:
{
field_name: "is_featured",
field_type: "boolean",
interface_type: "input", // Checkbox or toggle switch
is_required: false
}
Compatible Interfaces: input (only)
Default Behavior: Boolean fields typically default to false if not specified.
file
The file field type stores references to files in Vibe CMS's file management system. Files themselves are stored in Supabase Storage; fields contain file IDs.
Storage: PostgreSQL uuid (single_file) or uuid[] array (multiple_files)
Use Cases:
- Featured images and thumbnails
- PDF downloads and attachments
- Media galleries
- Document libraries
- Profile pictures and avatars
Validation: File IDs must reference valid files in the cms_files table
Single File Example:
{
field_name: "featured_image",
field_type: "file",
interface_type: "single_file",
is_required: false
}
Multiple Files Example:
{
field_name: "gallery",
field_type: "file",
interface_type: "multiple_files",
is_required: false
}
Compatible Interfaces: single_file, multiple_files
File References: When querying content, file fields return file IDs. Use the SDK's asset manager to resolve file URLs and metadata.
Interface Types Explained
Interface types control how content editors interact with fields in the admin UI. Each field type supports specific interfaces.
input
Single-line text input field, appropriate for short strings and simple values.
Compatible Field Types: text, number, boolean
Renders As:
- Text:
<input type="text"> - Number:
<input type="number"> - Boolean:
<input type="checkbox">or toggle switch
Best For: Titles, names, identifiers, simple values
textarea
Multi-line text input area for longer plain-text content.
Compatible Field Types: text (only)
Renders As: <textarea> element with resizable height
Best For: Descriptions, notes, plain-text content spanning multiple lines
Note: Use textarea for plain text; use markdown interface for formatted content.
markdown
Rich markdown editor with live preview, syntax highlighting, and formatting toolbar.
Compatible Field Types: markdown (only)
Renders As: Split-pane editor with markdown input and HTML preview
Features:
- Syntax highlighting
- Live preview
- Formatting toolbar (bold, italic, links, etc.)
- Image insertion
- Code block support
Best For: Blog posts, articles, documentation, any content requiring rich formatting
single_file
File picker interface that allows selecting one file from the file library.
Compatible Field Types: file (only)
Renders As: File browser with thumbnail preview and upload button
Interaction: Click to open file library, select one file, or upload new file
Best For: Featured images, single attachments, profile pictures
multiple_files
File picker interface that allows selecting multiple files from the file library.
Compatible Field Types: file (only)
Renders As: File browser with thumbnail grid and multi-select capability
Interaction: Click to open file library, select multiple files, drag to reorder
Best For: Image galleries, document collections, media libraries
Field Configuration
Required vs Optional Fields
Fields can be marked as required or optional using the is_required property:
{
field_name: "title",
field_type: "text",
interface_type: "input",
is_required: true // Content cannot be published without this field
}
Required Fields (is_required: true):
- Must be provided before content can be saved or published
- Enforced at the API level during content creation/update
- Indicated with visual markers in the admin UI
Optional Fields (is_required: false):
- Can be left empty
- No validation errors if omitted
- Useful for supplementary metadata
Best Practice: Mark only essential fields as required. Over-requiring fields creates friction for content editors.
Field Naming Conventions
Field names must follow strict database naming rules:
Rules:
- Must start with a lowercase letter (a-z)
- Can contain lowercase letters, numbers, and underscores
- Cannot contain spaces, hyphens, or special characters
- Must be unique within the collection
Valid Examples:
titlefeatured_imagepublish_dateauthor_namemeta_description
Invalid Examples:
Title(uppercase)featured-image(hyphen)publish date(space)1st_item(starts with number)
Reserved Names: The following field names are reserved and cannot be used:
id,created_at,updated_atdata,metadataselect,from,where,insert,update,delete,table- SQL keywords and system columns
Regex Pattern: ^[a-z][a-z0-9_]*$
Sort Order for Field Display
The sort_order property controls the order in which fields appear in the admin interface:
{
field_name: "title",
field_type: "text",
interface_type: "input",
is_required: true,
sort_order: 0 // First field
}
Ordering:
- Lower numbers appear first (0, 1, 2, ...)
- Fields with the same sort_order are ordered by creation date
- Sort order can be any non-negative integer
Best Practice: Use increments of 10 (0, 10, 20, ...) to leave room for inserting fields later.
Field Metadata
Every field in the database includes these properties:
{
id: "uuid", // Unique field ID
collection_id: "uuid", // Parent collection
account_id: "uuid", // Owner account
field_name: "title", // Database column name
field_type: "text", // Data type
interface_type: "input", // UI component
is_required: false, // Validation flag
sort_order: 0, // Display order
created_at: "2025-01-15T10:30:00Z",
updated_at: "2025-01-15T10:30:00Z",
created_by: "uuid", // User who created field
updated_by: "uuid" // User who last modified field
}
MCP Tools for Field Management
Vibe CMS provides MCP (Model Context Protocol) tools for programmatic field management. These tools are ideal for AI agents and automation scripts.
add_collection_field
Creates a new field in a collection.
Parameters:
{
collection_slug: "blog-posts", // Collection identifier
name: "author_name", // Field name (lowercase, valid identifier)
field_type: "text", // One of: text, markdown, number, boolean, file
interface_type: "input", // Must be compatible with field_type
is_required: false, // Optional, defaults to false
sort_order: 10 // Optional, defaults to 0
}
Example:
await mcp.add_collection_field({
collection_slug: "blog-posts",
name: "excerpt",
field_type: "text",
interface_type: "textarea",
is_required: false,
sort_order: 20
});
Validation:
- Field name must follow naming conventions
- Field name must be unique in collection
- Interface type must be compatible with field type
- Sort order must be non-negative
update_collection_field
Modifies an existing field's properties. Field name and field type typically cannot be changed after creation.
Parameters:
{
collection_slug: "blog-posts",
field_name: "excerpt",
interface_type: "textarea", // Optional: change UI component
is_required: true, // Optional: change required status
sort_order: 15 // Optional: change display order
}
Example:
await mcp.update_collection_field({
collection_slug: "blog-posts",
field_name: "excerpt",
is_required: true,
sort_order: 15
});
Limitations:
- Changing
field_namemay break existing content - Changing
field_typeis typically not allowed - Changing
interface_typemust maintain compatibility
reorder_collection_fields
Changes the display order of all fields in a collection at once.
Parameters:
{
collection_slug: "blog-posts",
field_names: ["title", "excerpt", "content", "author_name"] // Complete ordered list
}
Example:
await mcp.reorder_collection_fields({
collection_slug: "blog-posts",
field_names: [
"title",
"author_name",
"excerpt",
"content",
"featured_image",
"publish_date"
]
});
Requirements:
- Must include ALL fields in the collection
- Fields are assigned sort_order 0, 1, 2, ... based on array position
- Missing fields will cause an error
delete_collection_field
Permanently removes a field from a collection, including all data in that field across all content items.
Parameters:
{
collection_slug: "blog-posts",
field_name: "old_field",
confirm: true // Must be true to confirm deletion
}
Example:
await mcp.delete_collection_field({
collection_slug: "blog-posts",
field_name: "deprecated_field",
confirm: true
});
Warning:
- This operation is IRREVERSIBLE
- All content data in this field will be permanently deleted
- Use with extreme caution in production
Field Combinations and Patterns
text + input: Short Text
Perfect for single-line string values like titles, names, and labels.
{
field_name: "title",
field_type: "text",
interface_type: "input",
is_required: true,
sort_order: 0
}
Use Cases: Page titles, product names, author names, category labels
text + textarea: Long Text
Ideal for multi-line plain text like descriptions and notes.
{
field_name: "description",
field_type: "text",
interface_type: "textarea",
is_required: false,
sort_order: 10
}
Use Cases: Product descriptions, meta descriptions, internal notes, plain-text summaries
markdown + markdown: Rich Content
The standard pattern for formatted content like blog posts and articles.
{
field_name: "content",
field_type: "markdown",
interface_type: "markdown",
is_required: true,
sort_order: 20
}
Use Cases: Blog posts, documentation, article bodies, formatted descriptions
file + single_file: Single Image/Document
For content that needs one featured image or attachment.
{
field_name: "featured_image",
field_type: "file",
interface_type: "single_file",
is_required: false,
sort_order: 30
}
Use Cases: Featured images, hero images, profile pictures, single PDF downloads
file + multiple_files: Galleries and Collections
For content requiring multiple files like image galleries or document libraries.
{
field_name: "gallery",
field_type: "file",
interface_type: "multiple_files",
is_required: false,
sort_order: 40
}
Use Cases: Photo galleries, document libraries, portfolio items, product image sets
Best Practices
When to Use Each Field Type
text:
- Any string data
- When you need flexibility between single-line and multi-line input
- SEO fields (meta title, meta description)
- Identifiers and slugs
markdown:
- Long-form content requiring formatting
- Content with headings, lists, links, images
- Documentation and articles
- Any content that benefits from structure
number:
- Numeric values for calculations or comparisons
- Prices, quantities, ratings
- Sort orders and priorities
- Statistical data
boolean:
- Binary states and flags
- Feature toggles
- Enable/disable settings
- Conditional logic in templates
file:
- Images, videos, documents
- Media that needs professional asset management
- Content requiring file metadata (alt text, captions)
- Downloads and attachments
Field Naming Strategies
1. Use descriptive, self-documenting names:
// Good
field_name: "author_bio"
field_name: "publish_date"
field_name: "featured_image"
// Bad
field_name: "text1"
field_name: "data"
field_name: "field"
2. Use consistent prefixes for related fields:
field_name: "meta_title"
field_name: "meta_description"
field_name: "meta_keywords"
3. Avoid abbreviations unless universally understood:
// Good
field_name: "url"
field_name: "seo_title"
// Bad
field_name: "desc" // Use "description"
field_name: "img" // Use "image"
4. Use underscores for multi-word names:
field_name: "call_to_action_text" // Good
field_name: "callToActionText" // Bad (camelCase not allowed)
Schema Design Patterns
1. Core Content Pattern:
// Essential fields first
{ field_name: "title", field_type: "text", interface_type: "input", sort_order: 0 }
{ field_name: "slug", field_type: "text", interface_type: "input", sort_order: 10 }
{ field_name: "content", field_type: "markdown", interface_type: "markdown", sort_order: 20 }
// Media and metadata
{ field_name: "featured_image", field_type: "file", interface_type: "single_file", sort_order: 30 }
{ field_name: "publish_date", field_type: "text", interface_type: "input", sort_order: 40 }
// SEO fields last
{ field_name: "meta_title", field_type: "text", interface_type: "input", sort_order: 50 }
{ field_name: "meta_description", field_type: "text", interface_type: "textarea", sort_order: 60 }
2. E-commerce Product Pattern:
{ field_name: "product_name", field_type: "text", interface_type: "input", is_required: true }
{ field_name: "sku", field_type: "text", interface_type: "input" }
{ field_name: "price", field_type: "number", interface_type: "input", is_required: true }
{ field_name: "description", field_type: "markdown", interface_type: "markdown" }
{ field_name: "images", field_type: "file", interface_type: "multiple_files" }
{ field_name: "in_stock", field_type: "boolean", interface_type: "input" }
3. Author/Team Member Pattern:
{ field_name: "full_name", field_type: "text", interface_type: "input", is_required: true }
{ field_name: "role", field_type: "text", interface_type: "input" }
{ field_name: "bio", field_type: "markdown", interface_type: "markdown" }
{ field_name: "profile_picture", field_type: "file", interface_type: "single_file" }
{ field_name: "email", field_type: "text", interface_type: "input" }
{ field_name: "is_featured", field_type: "boolean", interface_type: "input" }
Migration and Schema Changes
Planning Schema Changes:
- Additive changes are safe: Adding new optional fields doesn't break existing content
- Removing fields is destructive: Always back up data before deleting fields
- Renaming is risky: Rename = delete + create, which loses data
- Type changes are dangerous: Changing field types may corrupt existing data
Safe Migration Pattern:
// 1. Add new field
await mcp.add_collection_field({
collection_slug: "blog-posts",
name: "new_field",
field_type: "text",
interface_type: "input",
is_required: false
});
// 2. Migrate data programmatically (if needed)
const posts = await cms.collection("blog-posts").all();
for (const post of posts) {
// Transform and update content
}
// 3. Mark old field as deprecated (or delete if truly unused)
// Note: No "deprecated" flag exists; use naming convention like "old_field_deprecated"
Risky Migration Pattern (avoid if possible):
// Renaming a field = delete old + create new = DATA LOSS
// Instead: Create new field, migrate data, then delete old field
Validation Strategies
1. Use is_required for essential fields:
{ field_name: "title", is_required: true } // Cannot publish without title
{ field_name: "excerpt", is_required: false } // Optional enhancement
2. Implement application-level validation for complex rules:
- Email format validation
- URL format validation
- Character limits
- Regex pattern matching
- Cross-field dependencies
3. Use field types to enforce basic data types:
numberensures numeric valuesbooleanensures true/falsefileensures valid file references
4. Leverage interface types for UX-driven validation:
inputfor short texttextareafor long textmarkdownfor structured content
Database Schema Reference
The cms_collection_fields table structure:
CREATE TABLE cms_collection_fields (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
collection_id UUID NOT NULL REFERENCES cms_collections(id) ON DELETE CASCADE,
account_id UUID NOT NULL REFERENCES basejump.accounts(id) ON DELETE CASCADE,
field_name TEXT NOT NULL,
field_type TEXT NOT NULL CHECK (field_type IN ('text', 'markdown', 'number', 'boolean', 'file')),
interface_type TEXT NOT NULL CHECK (interface_type IN ('input', 'textarea', 'markdown', 'single_file', 'multiple_files')),
is_required BOOLEAN NOT NULL DEFAULT false,
sort_order INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
created_by UUID REFERENCES auth.users(id),
updated_by UUID REFERENCES auth.users(id),
UNIQUE (collection_id, field_name)
);
Key Constraints:
field_typemust be one of: text, markdown, number, boolean, fileinterface_typemust be one of: input, textarea, markdown, single_file, multiple_filesfield_namemust be unique within the collection- Cascade deletion: removing a collection deletes all its fields
Field Type Compatibility Matrix
| Field Type | Compatible Interfaces | Use Cases |
|---|---|---|
| text | input, textarea | Titles, descriptions, labels, plain text |
| markdown | markdown | Blog posts, articles, rich content |
| number | input | Prices, quantities, ratings, counts |
| boolean | input | Flags, toggles, true/false states |
| file | single_file, multiple_files | Images, documents, media assets |
Summary
This chapter covered:
- Five field types: text, markdown, number, boolean, file
- Five interface types: input, textarea, markdown, single_file, multiple_files
- Field configuration: Required fields, naming conventions, sort order
- MCP tools: add_collection_field, update_collection_field, reorder_collection_fields, delete_collection_field
- Common patterns: Schema design for blogs, products, team members
- Best practices: Naming, validation, migrations, schema evolution
With this knowledge, you can design flexible, type-safe content schemas that meet your application's needs while providing an excellent editing experience.
Next Steps
- Chapter 7: Content Management: Learn to create, update, and query content items
- Chapter 8: Localization: Add multi-language support to your collections
- Chapter 9: File Management: Master file uploads, organization, and asset management
Need Help? Visit the Troubleshooting Guide or join our Discord community.