Field types reference
| Type | Storage | Options | API in/out |
|---|---|---|---|
| text | TEXT | min, max, pattern, unique, encrypted | string |
| number | REAL | min, max, unique | number |
| bool | INTEGER (0/1) | — | boolean |
TEXT | min, max, unique, encrypted | string (validated) | |
| url | TEXT | min, max, unique, encrypted | string (http/https) |
| date | INTEGER (unix sec) | — | in: number or ISO; out: number |
| autodate | INTEGER | onCreate, onUpdate | server-managed |
| select | TEXT (single) / TEXT JSON (multi) | values (req’d), multiple | string or string[] |
| relation | TEXT (target id) | cascade | string (id) |
| file | TEXT (filename) / TEXT JSON (multi) | maxSize, mimeTypes, multiple, protected | string or string[] |
| json | TEXT (JSON) | encrypted | any |
| password | TEXT (Argon2 hash) | min, max | write-only; never returned |
| editor | TEXT (HTML) | max | string (HTML) |
| geoPoint | TEXT JSON {lat,lng} | — | {lat,lng} |
Common to all: required, system (read-only flag).
{ "name": "title", "type": "text", "required": true, "options": { "min": 3, "max": 200, "pattern": "^[a-z0-9-]+$", "unique": true } }min/max— character countpattern— JS regex (string)unique— DB-side check at validate timeencrypted— AES-GCM at rest
number
Section titled “number”{ "name": "age", "type": "number", "options": { "min": 0, "max": 120 } }Stored as SQLite REAL — handles floats. min/max are value bounds.
{ "name": "published", "type": "bool" }Stored as 0/1 integer. API in/out is boolean.
{ "name": "email", "type": "email", "options": { "unique": true } }Format check: ^[^\s@]+@[^\s@]+\.[^\s@]+$. Otherwise like text.
{ "name": "site", "type": "url" }Format check: must start with http:// or https://.
{ "name": "starts_at", "type": "date" }Accepts on input: unix seconds (number) or any Date.parse-able string.
Always returns unix seconds.
autodate
Section titled “autodate”{ "name": "published_at", "type": "autodate", "onCreate": false, "onUpdate": true }Server-managed. onCreate: true sets it on insert; onUpdate: true
refreshes it on every PATCH. The system fields created and updated
are autodate fields with both flags on — you can’t redefine them.
select
Section titled “select”// single{ "name": "status", "type": "select", "options": { "values": ["draft", "live", "archived"] } }
// multi{ "name": "tags", "type": "select", "options": { "values": ["a", "b", "c"], "multiple": true } }values is required — empty rejects everything. Multi stored as a JSON
array; UI uses PrimeReact’s MultiSelect with chips.
relation
Section titled “relation”{ "name": "author", "type": "relation", "collection": "users", "options": { "cascade": "setNull" } }collection = target collection name (string). The record stores the
target’s id.
cascade modes (when the referenced record is deleted):
"setNull"(default) — bulk SQL update clearing the FK column."cascade"— recursively delete referencing records (cycle-protected)."restrict"— refuse the delete with409while references exist.
Existence is checked at write time — pointing at a non-existent record
returns 422.
{ "name": "avatar", "type": "file", "options": { "maxSize": 5242880, "mimeTypes": ["image/*"], "multiple": false, "protected": false } }maxSize— bytes;0= unlimitedmimeTypes— patterns;image/*matches anyimage/*multiple— store an array of filenames (JSON)protected— gates GET behind a?token=<jwt>; see Files
The record stores filenames; the bytes live in <dataDir>/uploads/.
{ "name": "metadata", "type": "json", "options": { "encrypted": true } }Any JSON-serializable value. Stored as JSON.stringify’d text. encrypted
puts the stringified value through AES-GCM at rest.
password
Section titled “password”{ "name": "secret", "type": "password", "options": { "min": 8 } }Hashed via Bun.password.hash (Argon2 by default) on write. Never returned
from the API. The records API automatically strips password fields from
all responses.
editor
Section titled “editor”{ "name": "body", "type": "editor", "options": { "max": 100000 } }Stored as HTML string. Admin UI uses Quill for editing.
geoPoint
Section titled “geoPoint”{ "name": "location", "type": "geoPoint" }{ lat: number, lng: number } with lat ∈ [-90, 90] and lng ∈ [-180, 180].
Stored as JSON.
Implicit fields (auth collections only)
Section titled “Implicit fields (auth collections only)”Auto-injected on auth-collection create:
email— typeemail, required, unique, markedimplicit: trueverified— typebool, default false, markedimplicit: true
You can edit their options but not their names or types. They’re stored on
vaultbase_users, not the per-collection table.
System fields
Section titled “System fields”Always present, never editable, never declarable as user fields:
id— text, UUID, set on createcreated_at(returned ascreated) — autodate onCreateupdated_at(returned asupdated) — autodate onUpdate