Skip to content

Properties

Properties define the columns in your database table and how they are rendered in the admin UI. Each property has a type that determines:

  • The database column type (via Drizzle schema generation)
  • The form field component
  • The table cell renderer
  • The validation rules
TypeDescriptionPostgreSQL Column
stringText, select, markdown, file upload, URL, emailvarchar, text, jsonb
numberInteger, decimal, currencyinteger, numeric, bigint, serial
booleanTrue/false toggleboolean
dateDate, datetime, timestamptimestamp, date
arrayOrdered list of valuesjsonb
mapKey-value objectjsonb
geopointLatitude/longitude pairjsonb
referenceEmbedded reference to another entityvarchar (stores ID)
relationSQL foreign key relationUses the relations array

All property types share these options:

PropertyTypeDescription
typestringRequired. Data type (see above)
namestringRequired. Display label
descriptionstringHelp text shown below the field
columnWidthnumberColumn width in pixels (table view)
readOnlybooleanPrevent editing
disabledboolean | PropertyDisabledConfigDisable with optional tooltip
hideFromCollectionbooleanHide from table view
defaultValueanyDefault value for new entities
validationobjectValidation rules
FieldReact.ComponentTypeCustom field component
PreviewReact.ComponentTypeCustom table cell component
propertyConfigstringRegistered property config key
editablebooleanEnable inline editing in table (default: true)
name: {
type: "string",
name: "Name",
validation: { required: true, min: 2, max: 200 }
}
description: {
type: "string",
name: "Description",
multiline: true, // Textarea
markdown: true // Markdown editor
}
category: {
type: "string",
name: "Category",
enum: [
{ id: "electronics", label: "Electronics", color: "blueDark" },
{ id: "clothing", label: "Clothing", color: "pinkLight" },
]
}
email: {
type: "string",
name: "Email",
email: true, // Email validation
validation: { required: true }
}
website: {
type: "string",
name: "Website",
url: true // URL validation
}
avatar: {
type: "string",
name: "Avatar",
storage: { // File upload
storagePath: "avatars",
acceptedFiles: ["image/*"],
maxSize: 2 * 1024 * 1024
}
}
PropertyTypeDescription
multilinebooleanRender as textarea
markdownbooleanRender as markdown editor
emailbooleanEmail format validation
urlbooleanURL format validation
storageStorageConfigEnable file upload
enumEnumValuesRender as select dropdown
multiSelectbooleanAllow multiple enum selections
columnTypestringDatabase column: "varchar", "text"
isIdstringID generation: "uuid", "cuid", "increment", "manual"
userSelectbooleanRender as a user picker
price: {
type: "number",
name: "Price",
validation: { required: true, min: 0 }
}
quantity: {
type: "number",
name: "Quantity",
columnType: "integer" // Store as integer
}
PropertyTypeDescription
enumEnumValuesRender as select with numeric values
columnTypestring"integer", "bigint", "numeric", "serial", "smallint"
isIdstringID generation strategy
active: {
type: "boolean",
name: "Active",
defaultValue: true
}

Switch field

created_at: {
type: "date",
name: "Created At",
autoValue: "on_create", // Set automatically on creation
readOnly: true
}
updated_at: {
type: "date",
name: "Updated At",
autoValue: "on_update" // Set automatically on every save
}
event_date: {
type: "date",
name: "Event Date",
mode: "date" // Date only (no time)
}

Date field

PropertyTypeDescription
mode"date" | "date_time"Date only or date + time (default: "date_time")
autoValue"on_create" | "on_update"Auto-set timestamps
columnTypestring"timestamp", "date"
tags: {
type: "array",
name: "Tags",
of: { type: "string" } // Array of strings
}
images: {
type: "array",
name: "Images",
of: {
type: "string",
storage: { storagePath: "images", acceptedFiles: ["image/*"] }
}
}
// Block editor (multiple types)
content: {
type: "array",
name: "Content Blocks",
oneOf: {
properties: {
text: {
type: "map",
properties: {
body: { type: "string", name: "Body", markdown: true }
}
},
image: {
type: "map",
properties: {
src: { type: "string", name: "Image", storage: { ... } },
caption: { type: "string", name: "Caption" }
}
}
}
}
}

Block field

address: {
type: "map",
name: "Address",
properties: {
street: { type: "string", name: "Street" },
city: { type: "string", name: "City" },
zip: { type: "string", name: "ZIP Code" },
country: { type: "string", name: "Country" }
}
}
metadata: {
type: "map",
name: "Metadata",
keyValue: true // Free-form key-value editor
}

Group field

Used with string or number properties to render selects:

// Simple array
enum: ["draft", "published", "archived"]
// With labels
enum: [
{ id: "draft", label: "Draft" },
{ id: "published", label: "Published" },
{ id: "archived", label: "Archived" }
]
// With colors (for Kanban columns and chips)
enum: [
{ id: "draft", label: "Draft", color: "grayDark" },
{ id: "published", label: "Published", color: "greenDark" },
{ id: "archived", label: "Archived", color: "orangeDark" }
]

Select field

validation: {
required: true, // Field is required
unique: true, // Must be unique in the table
requiredMessage: "Custom error message",
// String-specific
min: 2, // Minimum length
max: 200, // Maximum length
matches: /^[a-z]+$/, // Regex pattern
email: true, // Email format
url: true, // URL format
// Number-specific
min: 0, // Minimum value
max: 1000, // Maximum value
integer: true, // Must be integer
// Array-specific
min: 1, // Minimum items
max: 10, // Maximum items
}

Dynamically change property config based on entity values:

price: {
type: "number",
name: "Price",
dynamicProps: ({ values }) => ({
disabled: values.is_free === true,
validation: values.is_free ? {} : { required: true, min: 0 }
})
}