ObjectStackObjectStack

Data Modeling

Objects, fields, relationships, validation, CEL formulas, and a compiled query AST — the ObjectQL layer every other module builds on.

Data Modeling

Every ObjectStack application starts here: you declare objects (business entities), their fields, relationships, and validation rules as typed metadata, and the platform derives the database schema, REST API, permission surface, and UI from that single definition. This module is the practical documentation for the ObjectQL layer — the Data Protocol specified normatively in the ObjectQL spec.

A real object definition looks like this (from the CRM example app):

import { ObjectSchema, Field } from '@objectstack/spec/data';

export const Lead = ObjectSchema.create({
  name: 'crm_lead',
  label: 'Lead',
  pluralLabel: 'Leads',
  icon: 'funnel',
  description: 'An inbound prospect not yet qualified as an opportunity.',
  fields: {
    name: Field.text({ label: 'Lead Name', required: true, searchable: true, maxLength: 200 }),
    email: Field.email({ label: 'Email', searchable: true }),
    phone: Field.phone({ label: 'Phone' }),
    company: Field.text({ label: 'Company', searchable: true, maxLength: 200 }),
  },
});

That one definition is enough to get a persisted table, CRUD + query endpoints, permission checks, and generated list views and forms.

What the data layer actually gives you

  • A full spectrum of field types — from text, currency, and lookup/master_detail relationships to formula, summary, signature, and vector (with index config for AI embeddings). See the Field Types gallery.
  • Validation as metadata — required/format rules, CEL script validation with access to previous.<field>, uniqueness via indexes, and severity levels — enforced identically in API, UI, and automation.
  • CEL expressions — formula fields and computed defaults share one expression language (Expressions).
  • A compiled query AST — queries are JSON documents validated against the protocol, then compiled by a driver into native queries with joins, aggregations, window functions, HAVING, and subqueries. The query cheat sheet covers the syntax; the spec is normative.
  • Four database drivers in this repodriver-sql (PostgreSQL / MySQL / SQLite via Knex), driver-mongodb, driver-memory (in-memory, for tests and demos), and driver-sqlite-wasm (SQLite in the browser / WebContainers). The same model runs unchanged on any of them.
  • External datasource federation — introspect an existing external database, import selected tables into the catalog, and query them alongside native objects (External Datasources).

What's in this module

On this page