Concepts
Digital Objects
The core abstraction — typed, versioned, event-sourced entities defined via the Noun() function.
Every entity in headless.ly is a Digital Object — a typed, versioned, event-sourced entity with an immutable history, relationships to other objects, and actions you can perform on it.
Defining a Noun
Entities are defined using the Noun() function from digital-objects. Zero dependencies. Zero codegen. Full TypeScript inference.
import { Noun } from 'digital-objects'
export const Contact = Noun('Contact', {
name: 'string!',
email: 'string?#',
phone: 'string?',
title: 'string?',
stage: 'Lead | Qualified | Customer | Churned | Partner',
source: 'string?',
organization: '-> Organization.contacts',
deals: '<- Deal.contact[]',
messages: '<- Message.contact[]',
qualify: 'Qualified',
capture: 'Captured',
assign: 'Assigned',
merge: 'Merged',
enrich: 'Enriched',
})Property Value Patterns
Every property value tells the parser what it is:
| Pattern | Meaning | Example |
|---|---|---|
| Type string | Data property | 'string!', 'number?', 'datetime!' |
| Arrow syntax | Relationship | '-> Organization.contacts', '<- Deal.contact[]' |
| Pipe-separated PascalCase | Enum | 'Lead | Qualified | Customer' |
| Single PascalCase word | Verb declaration | 'Qualified', 'Captured' |
null | Opt out of inherited verb | update: null |
Type Modifiers
| Modifier | Meaning |
|---|---|
! | Required |
? | Optional |
# | Indexed |
Relationships
organization: '-> Organization.contacts' // belongs to Organization
deals: '<- Deal.contact[]' // has many Deals-> is a forward reference (many-to-one). <- is a reverse reference (one-to-many). [] indicates a collection.
Immutability
Opt out of CRUD verbs with null:
export const Event = Noun('Event', {
name: 'string!',
timestamp: 'datetime!',
update: null,
delete: null,
})Event.update() is a TypeScript error — the Noun definition above removes it.