Docs / SDK / Entity System
Entity System
Entities are the data objects in your workspace -- contacts, invoices, tasks, projects. The entity system lets you define their types, fields, statuses, relations, and inspector panels as pure data.
Defining an entity type
Use the entityType() builder to define an entity. Every entity type has a name, icon, accent color, display field, and optional statuses, relations, and actions:
import { entityType } from "@substrateui/substrate/entities";
const contact = entityType("contact", {
name: "Contact",
namePlural: "Contacts",
icon: "user",
accent: "blue",
module: "crm",
displayField: "name",
secondaryField: "company",
statusField: "status",
searchFields: ["name", "email", "company"],
statuses: [
{ id: "active", label: "Active", color: "green", default: true },
{ id: "inactive", label: "Inactive", color: "neutral" },
{ id: "lead", label: "Lead", color: "yellow" },
{ id: "churned", label: "Churned", color: "red", terminal: true },
],
relations: [
{ target: "company", type: "belongs-to", label: "Company", showInInspector: true },
{ target: "deal", type: "has-many", label: "Deals", navigable: true },
{ target: "activity", type: "has-many", label: "Activities" },
],
actions: [
{ id: "email", label: "Send Email", icon: "mail", shortcut: "E" },
{ id: "call", label: "Log Call", icon: "phone" },
{ id: "archive", label: "Archive", icon: "archive", confirm: "Archive this contact?" },
{ id: "delete", label: "Delete", icon: "trash", danger: true, confirm: true },
],
});Statuses
Each status has an id, display label, and color (any AccentColor). Mark one status as default: true for new entities, and use terminal: true for closed/completed states that remove the entity from active views.
Relations
Relations connect entity types to each other. The target field references another entity type's ID, and type can be has-many, belongs-to, many-to-many, or has-one. Set showInInspector: true to display the relation in the entity inspector, and navigable: true to allow clicking through to related entities.
Entity inspector
The inspector is a detail panel that displays when an entity is selected. Define it with entityInspector(). It supports a header, DNA card (key metrics at a glance), and tabbed sections:
import {
entityInspector,
inspectorTab,
fieldSection,
entityField,
metric,
} from "@substrateui/substrate/entities";
const contactInspector = entityInspector("contact", {
header: {
showIcon: true,
showStatus: true,
titleField: "name",
subtitleField: "company",
editableTitle: true,
useEntityAccent: true,
},
dna: {
metrics: [
metric("deals", "Open Deals", "dealCount", { format: "number", accent: "blue" }),
metric("value", "Pipeline Value", "totalValue", { format: "currency", accent: "green" }),
metric("last-contact", "Last Contact", "lastContactDate", { format: "date" }),
],
layout: "horizontal",
},
tabs: [
inspectorTab("details", "Details", "details", {
sections: [
fieldSection("contact-info", [
entityField("email", "email", { format: "email", copyable: true }),
entityField("phone", "phone", { format: "phone" }),
entityField("title", "jobTitle", { label: "Job Title" }),
entityField("company", "companyId", { format: "entity-link", linkedEntityType: "company" }),
], { label: "Contact Info", columns: 2 }),
fieldSection("address", [
entityField("street", "address.street"),
entityField("city", "address.city"),
entityField("state", "address.state"),
entityField("zip", "address.zip"),
], { label: "Address", collapsible: true, defaultExpanded: false }),
],
}),
inspectorTab("deals", "Deals", "related", {
relatedConfig: { entityType: "deal", displayMode: "table" },
badge: 3,
}),
inspectorTab("activity", "Activity", "activity"),
],
inlineEditing: true,
crossNavigation: true,
activityFeed: { enabled: true, showTimestamps: true },
width: 360,
});DNA card
The DNA card shows key metrics at the top of the inspector. Each metric references a field path and can display as a number, currency, percentage, date, duration, or text. Add a trendField to show change direction. Layout can be horizontal, vertical, or grid.
Entity picker
The entity picker is a modal or popover for selecting entities. Use it in relation fields, assignment selectors, or anywhere you need to reference an entity:
import { entityPicker } from "@substrateui/substrate/entities";
const contactPicker = entityPicker({
entityTypes: ["contact"],
mode: "combobox",
search: { placeholder: "Search contacts...", fields: ["name", "email"] },
showRecent: true,
maxRecent: 5,
createNew: true,
multiple: false,
});Builder reference
All entity builders are exported from @substrateui/substrate/entities:
| Function | Returns |
|---|---|
| entityType(id, config) | EntityTypeDef |
| entityInspector(entityTypeId, config) | EntityInspectorConfig |
| entityPicker(config?) | EntityPickerConfig |
| entityHub(config?) | EntityHubConfig |
| entityRegistry(types, groups?) | EntityRegistryConfig |
| metric(id, label, field, config?) | EntityMetric |
| inspectorTab(id, label, type, config?) | EntityInspectorTab |
| fieldSection(id, fields, config?) | EntityFieldSection |
| entityField(id, field, config?) | EntityFieldDef |