Field Reference
Complete guide to adding and configuring field types in Content Engine, including Postgres mappings, Zod validation, and AdminCP controls.
Content Engine provides field descriptors exported from @vitnode/core/content via the field helper. Each field generates a typed Drizzle column, Zod validation schemas, and an interactive AdminCP input automatically.
Supported Field Types
| Field Method | Postgres Column | Zod Schema | AdminCP Form Control |
|---|---|---|---|
field.text() | varchar(length) | z.string() | Text Input |
field.textarea() | text() | z.string() | Textarea |
field.number() | integer() / numeric() | z.number() | Number Input |
field.boolean() | boolean() | z.boolean() | Switch Toggle |
field.enum() | varchar(length) | z.enum([...]) | Select Dropdown |
field.dateTime() | timestamp() | z.date() | Date / Time Picker |
field.slug() | varchar(length) | z.string() | Slug Generator |
field.user() | integer() (FK core_users) | z.number() | User Combobox |
field.user({ multiple: true }) | Junction table | z.array(z.number()) | Multi-user Combobox |
field.file() | integer() (FK core_files) | z.number() | Drag-and-drop File Upload |
field.file({ multiple: true }) | Junction table | z.array(z.number()) | Multi-file Gallery Uploader |
Field Configurations
Text and Strings
Configure string length, required state, and multi-language support:
import { defineContentType, field } from "@vitnode/core/content"
export const postContentType = defineContentType({
id: "blog.post",
tableName: "blog_posts",
fields: {
title: field.text({
required: true,
minLength: 3,
maxLength: 200,
searchable: true,
translatable: true,
}),
summary: field.textarea({
maxLength: 500,
translatable: true,
}),
},
})Numbers, Booleans, and Enums
fields: {
views: field.number({
defaultValue: 0,
min: 0,
sortable: true,
}),
featured: field.boolean({
defaultValue: false,
}),
status: field.enum({
values: ["draft", "published", "archived"] as const,
defaultValue: "draft",
}),
}Slugs, Dates, and User Relations
Auto-generate SEO slugs from other fields, pick dates, or link authors:
fields: {
slug: field.slug({
from: "title", // Automatically generated from title
required: true,
}),
publishedAt: field.dateTime({
defaultValue: () => new Date(),
}),
author: field.user({
required: true,
}),
contributors: field.user({
multiple: true,
}),
}Single and Multi-File Uploads
VitNode connects file fields directly to core_files with storage adapters (Local disk, S3, Cloudflare R2):
fields: {
// Single cover image (max 5 MB)
coverImage: field.file({
required: false,
maxBytes: 5 * 1024 * 1024,
allowedExtensions: ["jpg", "png", "webp"],
allowedMimeTypes: ["image/jpeg", "image/png", "image/webp"],
}),
// Gallery of screenshots
gallery: field.file({
multiple: true,
maxFiles: 10,
maxBytes: 10 * 1024 * 1024,
allowedExtensions: ["jpg", "png", "webp"],
}),
}Automatic Multipart Upload Pipeline
In the AdminCP, AutoFormFile uploads attachments via TanStack Query and standard multipart API routes (POST /api/.../uploads/{field}). Uploaded records are stored in core_files and assigned by ID.
Common Field Options
Every field descriptor accepts these standard attributes:
Prop
Type
Learn More
Defining a Content Type
Declare a Content Engine content type once to get a Postgres table, typed CRUD routes, and interactive AdminCP screens.
Database & Migrations
How the Content Engine maps content models to PostgreSQL tables using createContentModel, handles system columns, and executes Drizzle Kit migrations.