Tables & Fields

Tables define your data models. Each table has an id, name, fields, and optional permissions, indexes, and views.

Table Structure

Each table has an id, name, fields array, and optional permissions and indexes.

YAML
tables:
  - id: 1
    name: tasks
    fields:
      - id: 1
        name: title
        type: single-line-text
        required: true
      - id: 2
        name: completed
        type: checkbox
    permissions:
      create: authenticated
      read: all
      update: [admin, member]
      delete: [admin]
    indexes:
      - fields: [title]
        unique: true

Table Properties

Each table in the tables array accepts the following properties.

PropertyDescription
idUnique integer identifier for the table.
nameTable name. Max 63 characters.
fieldsArray of field definitions. At least one field is required.
primaryKeyColumn(s) used as primary key. Defaults to an auto-generated id column.
indexesArray of index definitions for query performance and uniqueness enforcement.
uniqueConstraintsArray of multi-column uniqueness constraints.
foreignKeysExplicit foreign key definitions for cross-table referential integrity.
constraintsArray of check constraints with SQL expressions for data validation.
viewsSaved views with pre-configured filters, sorting, and visible fields.
permissionsRBAC permissions object controlling create, read, update, delete, and comment operations.
allowDestructiveBoolean. When true, allows destructive schema migrations (column drops, type changes). Defaults to false.

Base Field Properties

Every field has these base properties: id (unique integer), name (identifier), type (one of 41 types), and optional required, unique, indexed, and default.

PropertyDescription
idUnique integer identifier for the field within the table.
nameField name used as the column identifier. Lowercase, digits, underscores (^[a-z][a-z0-9_]*).
typeOne of the 41 available field types (e.g., single-line-text, integer, checkbox).
requiredBoolean. When true, the field must have a value for every record.
uniqueBoolean. When true, no two records can have the same value.
indexedBoolean. When true, creates a database index on this field for faster queries.
defaultDefault value assigned when a record is created without specifying this field.

41 Field Types

Field types are organized into 9 categories:

Text Fields

Fields for textual content, from short labels to rich formatted text and structured strings.

single-line-textlong-textrich-textemailurlphone-numberbarcode
PropertyDescription
rich-text.maxLengthMaximum character count for rich-text fields. Validates on input.
rich-text.fullTextSearchBoolean. Enables full-text search indexing for rich-text and long-text fields.
barcode.formatBarcode encoding format: CODE128, EAN13, QR, UPC, etc.
YAML
fields:
  - id: 1
    name: title
    type: single-line-text
    required: true
  - id: 2
    name: notes
    type: rich-text
    maxLength: 5000
    fullTextSearch: true

Numeric Fields

Fields for numbers, currencies, percentages, ratings, and progress indicators.

integerdecimalcurrencypercentageratingprogress
PropertyDescription
min / maxMinimum and maximum allowed values. Applies to integer, decimal, currency, and percentage.
precisionNumber of decimal places for decimal and currency fields (0–20).
currencyISO 4217 currency code (e.g., USD, EUR, GBP). Required for currency fields.
symbolPositionCurrency symbol placement: "before" ($100) or "after" (100€). Default: before.
thousandsSeparatorBoolean. Enable thousands grouping separator (1,000 vs 1000). Default: true.
negativeFormatDisplay format for negatives: "minus" (-100), "parentheses" ((100)), or "red" (∞100 in red).
rating.maxMaximum rating value (1–10). Default: 5.
rating.styleVisual style for rating display: "stars", "hearts", "thumbs", or "numeric".
progress.colorColor of the progress bar. Accepts any CSS color value.
YAML
fields:
  - id: 1
    name: price
    type: currency
    currency: USD
    precision: 2
    symbolPosition: before
  - id: 2
    name: satisfaction
    type: rating
    max: 5
    style: stars

Selection Fields

Fields for choosing from predefined options: single or multi-select with string arrays. Use the status field type for colored workflow states.

single-selectmulti-selectcheckboxstatus
PropertyDescription
optionsArray of strings defining the available choices (e.g., ["Low", "Medium", "High"]).
maxSelectionsMaximum number of choices for multi-select fields. No limit by default.
YAML
fields:
  - id: 1
    name: priority
    type: single-select
    options: [Low, Medium, High]
  - id: 2
    name: tags
    type: multi-select
    maxSelections: 5
    options: [Frontend, Backend, DevOps]

Date & Time Fields

Fields for dates, times, timestamps, and duration values.

datedatetimetimeduration
PropertyDescription
dateFormatDisplay format for dates: "YYYY-MM-DD", "MM/DD/YYYY", "DD/MM/YYYY", etc.
timeFormatTime display format: "12h" or "24h".
includeTimeBoolean. When true, date fields also capture time.
timezoneIANA timezone identifier (e.g., "America/New_York"). Defaults to UTC.
duration.formatDisplay format for duration fields: "hours:minutes", "minutes", "seconds", etc.

User & Audit Fields

Auto-populated fields tracking who created/updated/deleted a record and when. Requires auth to be configured.

usercreated-bycreated-atupdated-byupdated-atdeleted-bydeleted-at
PropertyDescription
userReference to a user. Allows selecting any user. Requires auth to be configured.
created-atTimestamp automatically set when the record is created. Read-only.
updated-atTimestamp automatically updated whenever the record is modified. Read-only.
deleted-atSoft-delete timestamp. NULL means the record is active; a timestamp means it has been deleted. Enables trash/restore lifecycle.
created-byReference to the user who created the record. Requires auth to be configured.
updated-byReference to the user who last updated the record. Requires auth to be configured.
deleted-byReference to the user who soft-deleted the record. Requires auth to be configured.
YAML
fields:
  - id: 1
    name: created
    type: created-at
  - id: 2
    name: updated
    type: updated-at
  - id: 3
    name: deleted
    type: deleted-at
  - id: 4
    name: author
    type: created-by
  - id: 5
    name: editor
    type: updated-by
  - id: 6
    name: remover
    type: deleted-by

Attachment Fields

single-attachmentmultiple-attachments
PropertyDescription
allowedFileTypesArray of allowed MIME types (e.g., ["image/png", "application/pdf"]). Empty = all types.
maxFileSizeMaximum file size in bytes. Example: 10485760 for 10 MB.
maxFilesMaximum number of files for multiple-attachments fields.
storageStorage backend: "local" (default) or "s3" for cloud storage.
generateThumbnail(s)Boolean. When true, automatically generates image thumbnails on upload.
storeMetadataBoolean. When true, stores file metadata (dimensions, EXIF, duration).

Computed Fields

formulaautonumber
PropertyDescription
formulaExpression string referencing other fields. Example: "price * quantity".
resultTypeExpected output type of the formula: "string", "integer", "decimal", "boolean", or "date".
formatDisplay format for the computed result (e.g., "0,0.00" for numbers).
prefixText prepended to autonumber values (e.g., "TKT-", "INV-").
startFromStarting value for autonumber sequence. Default: 1.
digitsMinimum digits for autonumber, zero-padded. Example: 5 → "00001".
YAML
fields:
  - id: 1
    name: total
    type: formula
    formula: "price * quantity"
    resultType: decimal
  - id: 2
    name: ticket_number
    type: autonumber
    prefix: "TKT-"
    startFrom: 1000
    digits: 5

Advanced Fields

jsonarraygeolocationcolorbutton
PropertyDescription
json.schemaJSON Schema object for validating json field contents.
array.itemTypeData type for array elements: "string", "number", "boolean", or "object".
array.maxItemsMaximum number of elements in an array field.
button.labelText displayed on the button. Supports $t: translation syntax.
button.actionAction triggered on click: "openUrl", "runScript", or "callWebhook".
button.urlURL to open or webhook to call. Supports {field_name} template variables.

Relational Fields

Four field types enable cross-table relationships: relationship, lookup, rollup, and count. These form a chain. Relationship defines the link, then lookup, rollup, and count derive data from it.

relationship

Creates a foreign-key link to another table. Foundation for all relational features.

PropertyDescription
relatedTableName of the target table to link to. Must match an existing table name.
relationTypeCardinality: "one-to-one", "many-to-one", "one-to-many", or "many-to-many".
foreignKeyCustom foreign key column name. Auto-generated if omitted.
displayFieldField from the related table shown in the UI (e.g., "name" instead of "id").
onDeleteReferential action on delete: "cascade", "set-null", "restrict", or "no-action".
onUpdateReferential action on update: "cascade", "set-null", "restrict", or "no-action".
reciprocalFieldField name for the inverse relationship on the related table.
allowMultipleBoolean. For many-to-many, allows selecting multiple related records.

lookup

Reads a field value from a related record via an existing relationship. Read-only and auto-updated.

PropertyDescription
relationshipFieldName of the relationship field to traverse (must exist in the same table).
relatedFieldField name on the related table whose value to display.
filtersOptional filter expression to narrow which related records are included.

rollup

Aggregates values from multiple related records (sum, avg, count, min, max, etc.).

PropertyDescription
relationshipFieldName of the relationship field connecting to the related table.
relatedFieldField on the related table to aggregate.
aggregationAggregation function: "sum", "avg", "min", "max", "count", "concat", or "array".
formatDisplay format for the aggregated result (e.g., "$0,0.00" for currency sums).
filtersOptional filter to include only matching related records in the aggregation.

count

Counts the number of related records. A simplified rollup with aggregation always set to count.

PropertyDescription
relationshipFieldName of the relationship field to count records from.
conditionsOptional filter expression to count only matching records.
YAML
tables:
  - name: customers
    fields:
      - { id: 1, name: email, type: email }
      - { id: 2, name: full_name, type: single-line-text }

  - name: orders
    fields:
      - { id: 1, name: customer, type: relationship,
          relatedTable: customers, relationType: many-to-one }
      - { id: 2, name: customer_email, type: lookup,
          relationshipField: customer, relatedField: email }
      - { id: 3, name: total, type: currency, currency: USD }

  - name: customers  # add rollup to customers
    fields:
      - { id: 3, name: order_count, type: count,
          relationshipField: orders }
      - { id: 4, name: total_spent, type: rollup,
          relationshipField: orders,
          relatedField: total, aggregation: sum }

Relational chain

Start with a relationship field to create the link, then use lookup, rollup, or count to derive data without duplication. Example: orders → customer (relationship) → customer_email (lookup).

Permissions (RBAC)

Table permissions use role-based access control. Each permission accepts: "all" (public), "authenticated" (logged-in users), or an array of role names.

PropertyDescription
createWho can create new records. Default: "authenticated".
readWho can view records. Default: "all".
updateWho can modify existing records. Default: "authenticated".
deleteWho can remove records. Default: "authenticated".
commentWho can add comments to records. Default: "authenticated".
fieldsObject mapping field names to per-field read/update permissions. Enables fine-grained access control.
inheritBoolean. When true, inherits permissions from a parent table or global defaults.
overrideBoolean. When true, these permissions override any inherited ones.
YAML
permissions:
  create: authenticated
  read: all
  update: [admin, member]
  delete: [admin]
  comment: authenticated
  fields:
    salary:
      read: [admin, hr]
      update: [admin]
    notes:
      read: [admin, member]
      update: [admin, member]

Three access levels

"all" for public access, "authenticated" for any logged-in user, or an array of role names like [admin, member] for specific roles.

Security best practice

Unauthorized access returns 404 (not 403) to prevent attackers from discovering which resources exist. This follows OWASP recommendations for resource enumeration prevention.

Indexes & Constraints

Optimize queries with indexes and enforce data integrity with uniqueness and check constraints.

Indexes

PropertyDescription
nameOptional human-readable name for the index (e.g., "idx_email").
fieldsArray of field names to index. Composite indexes list multiple fields.
uniqueBoolean. When true, enforces uniqueness across the indexed columns.
wherePartial index condition as SQL expression. Only rows matching the condition are indexed.

Unique Constraints

PropertyDescription
nameName for the unique constraint (e.g., "uq_email_org").
fieldsArray of field names that must be unique together (composite uniqueness).

Check Constraints

PropertyDescription
nameName for the check constraint (e.g., "chk_positive_price").
checkSQL boolean expression that must be true for every row (e.g., "price > 0").
YAML
tables:
  - name: products
    fields:
      - { id: 1, name: sku, type: single-line-text }
      - { id: 2, name: price, type: decimal, min: 0 }
      - { id: 3, name: category, type: single-line-text }
    indexes:
      - name: idx_sku
        fields: [sku]
        unique: true
      - name: idx_category_price
        fields: [category, price]
    uniqueConstraints:
      - name: uq_sku
        fields: [sku]
    constraints:
      - name: chk_positive_price
        check: "price > 0"