ObjectStackObjectStack

View

View protocol schemas

HTTP Method Enum & HTTP Request Schema Migrated to shared/http.zod.ts. Re-exported here for backward compatibility.

Source: packages/spec/src/ui/view.zod.ts

TypeScript Usage

import { AddRecordConfigSchema, AppearanceConfigSchema, CalendarConfigSchema, ColumnPrefixSchema, ColumnSummarySchema, ColumnSummaryConfigSchema, FormButtonConfigSchema, FormFieldSchema, FormFieldPublicPickerSchema, FormSectionSchema, FormViewSchema, GalleryConfigSchema, GanttConfigSchema, GanttQuickFilterSchema, GroupingConfigSchema, GroupingFieldSchema, HttpMethodSubsetSchema, HttpRequestSchema, KanbanConfigSchema, ListChartConfigSchema, ListColumnSchema, ListViewSchema, NavigationConfigSchema, NavigationModeSchema, ObjectListViewSchema, ObjectUserFiltersSchema, PaginationConfigSchema, RowColorConfigSchema, RowHeightSchema, SelectionConfigSchema, TimelineConfigSchema, TreeConfigSchema, UserActionsConfigSchema, UserFilterFieldSchema, UserFiltersSchema, ViewSchema, ViewDataSchema, ViewFilterRuleSchema, ViewItemSchema, ViewItemNameSchema, ViewItemWireSchema, ViewKindSchema, ViewScopeSchema, ViewSharingSchema, ViewTabSchema, VisualizationTypeSchema } from '@objectstack/spec/ui';
import type { AddRecordConfig, AppearanceConfig, CalendarConfig, ColumnPrefix, ColumnSummary, ColumnSummaryConfig, FormButtonConfig, FormField, FormFieldPublicPicker, FormSection, FormView, GalleryConfig, GanttConfig, GanttQuickFilter, GroupingConfig, HttpMethodSubset, HttpRequest, KanbanConfig, ListChartConfig, ListColumn, ListView, NavigationConfig, NavigationMode, PaginationConfig, RowColorConfig, RowHeight, SelectionConfig, TimelineConfig, TreeConfig, UserActionsConfig, UserFilterField, UserFilters, View, ViewData, ViewFilterRule, ViewItem, ViewItemName, ViewItemWire, ViewKind, ViewScope, ViewSharing, ViewTab, VisualizationType } from '@objectstack/spec/ui';

// Validate data
const result = AddRecordConfigSchema.parse(data);

AddRecordConfig

Add record entry point configuration

Properties

PropertyTypeRequiredDescription
enabledbooleanShow the add record entry point
positionEnum<'top' | 'bottom' | 'both'>Position of the add record button
modeEnum<'inline' | 'form' | 'modal'>How to add a new record
formViewstringoptionalNamed form view to use when mode is "form" or "modal"

AppearanceConfig

Appearance and visualization configuration

Properties

PropertyTypeRequiredDescription
showDescriptionbooleanShow the view description text
allowedVisualizationsEnum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>[]optionalWhitelist of visualization types users can switch between (e.g. ["grid", "gallery", "kanban"])

CalendarConfig

Properties

PropertyTypeRequiredDescription
startDateFieldstringField providing the event start date/time
endDateFieldstringoptionalField providing the event end date/time (defaults to a single-day event)
titleFieldstringField displayed as the event title
colorFieldstringoptionalField whose value determines the event color

ColumnPrefix

Compound-cell prefix configuration

Properties

PropertyTypeRequiredDescription
fieldstringField whose value renders before the cell value
typeEnum<'badge' | 'text'>How the prefix value is rendered

ColumnSummary

Aggregation function for column footer summary

Allowed Values

  • none
  • count
  • count_empty
  • count_filled
  • count_unique
  • percent_empty
  • percent_filled
  • sum
  • avg
  • min
  • max

ColumnSummaryConfig

Column footer summary configuration

Properties

PropertyTypeRequiredDescription
typeEnum<'none' | 'count' | 'count_empty' | 'count_filled' | 'count_unique' | 'percent_empty' | 'percent_filled' | 'sum' | 'avg' | 'min' | 'max'>Aggregation function
fieldstringoptionalField to aggregate (defaults to the column field)

FormButtonConfig

Properties

PropertyTypeRequiredDescription
showbooleanoptionalWhether the button is rendered (renderer default applies when omitted)
labelstring | Record<string, string>optionalButton label (i18n-capable; renderer default when omitted)

FormField

Properties

PropertyTypeRequiredDescription
fieldstringField name (snake_case)
typeEnum<'text' | 'textarea' | 'email' | 'url' | 'phone' | 'password' | 'secret' | 'markdown' | 'html' | 'richtext' | 'number' | 'currency' | 'percent' | 'date' | … +35 more>optionalField type (auto-infers widget if omitted)
options{ label: string; value: string; color?: string; default?: boolean; … }[]optionalOptions for select/multiselect/radio/checkboxes fields
referencestringoptionalTarget object name for lookup/master_detail fields
publicPicker{ displayFields?: string[]; maxResults?: integer; filter?: object[]; object?: string }optionalOpt this field into the anonymous public-form lookup picker (GET /forms/:slug/lookup/:field). Without it the route answers 403 LOOKUP_NOT_PUBLIC and the field is stripped from the rendered public form.
maxLengthnumberoptionalMaximum character length (for text/textarea/email/url/phone)
minLengthnumberoptionalMinimum character length
minnumberoptionalMinimum value (for number/currency/percent/slider)
maxnumberoptionalMaximum value
precisionnumberoptionalTotal digits (for number/currency)
scalenumberoptionalDecimal places
multiplebooleanoptionalAllow multiple values (for select/lookup/file/image)
labelstring | Record<string, string>optionalDisplay label override
placeholderstring | Record<string, string>optionalPlaceholder text
helpTextstring | Record<string, string>optionalHelp/hint text
readonlybooleanoptionalRead-only override
immutablebooleanoptionalEditable on create, locked once the record exists (e.g. machine names).
requiredbooleanoptionalRequired override
hiddenbooleanoptionalHidden override
colSpanintegeroptional[legacy — prefer span] Absolute column span (1-4). Fragile when the column count is derived per surface (mobile 1 / modal 2 / page 3-4): a fixed span only lines up at the width the author imagined. The renderer clamps it to the current column count. Prefer span.
spanEnum<'auto' | 'full'>optionalRelative field width. 'auto' (default — omit it): the renderer sizes the field from its widget type × the current column count (wide widgets like textarea/richtext/json/file/subform take the whole row). 'full': whole row at any column count. Prefer this over the absolute colSpan.
widgetstringoptionalCustom widget/component name (overrides type-based inference)
languagestringoptionalCode editor language (for type=code)
keyField{ field?: string; label?: string | Record<string, string>; placeholder?: string | Record<string, string>; helpText?: string | Record<string, string>; … }optionalKey column config for record-typed fields
dependsOnstringoptionalParent field name for cascading
visibleWhenstring | { dialect: Enum<'cel' | 'cron' | 'template'>; source?: string; ast?: any; meta?: object }optionalVisibility predicate (CEL) — field shown only when TRUE. Root: record (+ previous, parent) in runtime forms, or data in metadata forms. No current_user at field level — it is unbound here and the predicate would fault open (per-option visibleWhen is the surface that binds it). Inside a repeater data is the ROW, but it is still spelled data — a bare identifier is unbound and faults open too. e.g. Precord.priority == 'urgent'
visibleOnstring | { dialect: Enum<'cel' | 'cron' | 'template'>; source?: string; ast?: any; meta?: object }optional[DEPRECATED → visibleWhen] Visibility predicate (CEL). Normalized to visibleWhen at parse.
disclosureEnum<'inline' | 'popover'>optionalComposite rendering: inline bordered box (default) or a summary line + gear popover (progressive disclosure).
fields[FormField](#formfield)[]optionalSub-fields for composite/repeater/record types

Allowed Values: FormField.type

  • text
  • textarea
  • email
  • url
  • phone
  • password
  • secret
  • markdown
  • html
  • richtext
  • number
  • currency
  • percent
  • date
  • datetime
  • time
  • boolean
  • toggle
  • select
  • multiselect
  • radio
  • checkboxes
  • lookup
  • master_detail
  • tree
  • user
  • image
  • file
  • avatar
  • video
  • audio
  • formula
  • summary
  • autonumber
  • composite
  • repeater
  • record
  • location
  • address
  • code
  • json
  • color
  • rating
  • slider
  • signature
  • qrcode
  • progress
  • tags
  • vector

FormFieldPublicPicker

Public-lookup opt-in: enables GET /forms/:slug/lookup/:field for this field on an anonymous public form (without it the route answers 403 LOOKUP_NOT_PUBLIC).

Properties

PropertyTypeRequiredDescription
displayFieldsstring[]optionalFields projected into each picker result (with id); the visitor's search matches contains on the first entry. At most 5 (the route projects no more); omitted → ['name'].
maxResultsintegeroptionalMaximum rows a lookup returns (default 20, hard ceiling 50 — the route clamps; anonymous visitors cannot paginate past it).
filter{ field: string; operator: Enum<'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | … +14 more>; value?: string | number | boolean | null | (string | number)[] }[]optionalStatic pre-filter rows ANDed ahead of the visitor's search (e.g. only active records are searchable). Same { field, operator, value } dialect as list-view filters.
objectstringoptionalReferenced-object override for the picker search; omitted → resolved from the field definition (referenceTo).

FormSection

Properties

PropertyTypeRequiredDescription
namestringoptionalStable section identifier for i18n lookup (snake_case)
labelstring | Record<string, string>optionalDisplay label — the default-language string, or an inline locale map ({ en, "zh-CN" }) resolved at render time
descriptionstringoptionalOptional description rendered under the section header.
collapsiblebooleanoptional
collapsedbooleanoptional
visibleWhenstring | { dialect: Enum<'cel' | 'cron' | 'template'>; source?: string; ast?: any; meta?: object }optionalVisibility predicate (CEL) — section shown only when TRUE. Root: record (+ previous, parent) in runtime forms, or data in metadata forms. No current_user at section level — it is unbound here and the predicate would fault open.
visibleOnstring | { dialect: Enum<'cel' | 'cron' | 'template'>; source?: string; ast?: any; meta?: object }optional[DEPRECATED → visibleWhen] Visibility predicate (CEL). Hides the whole section when false. Normalized to visibleWhen at parse.
columnsEnum<'1' | '2' | '3' | '4'> | 1 | 2 | 3 | 4optional
paneEnum<'primary' | 'secondary'>optionalSplit pane this section renders in (split forms only; a parse error elsewhere). Omitted → first section 'primary', others 'secondary'.
fields(string | { field: string; type?: Enum<'text' | 'textarea' | 'email' | 'url' | 'phone' | 'password' | 'secret' | … +42 more>; options?: object[]; reference?: string; … })[]

FormView

Properties

PropertyTypeRequiredDescription
typeEnum<'simple' | 'tabbed' | 'wizard' | 'split' | 'drawer' | 'modal'>optional
layoutEnum<'vertical' | 'horizontal' | 'inline' | 'grid'>optionalField layout direction
columnsintegeroptionalNumber of columns for the form body
titlestringoptionalForm title
descriptionstringoptionalForm description
defaultTabstringoptionalInitially active tab (tabbed forms)
tabPositionEnum<'top' | 'bottom' | 'left' | 'right'>optionalTab strip position (tabbed forms)
allowSkipbooleanoptionalAllow skipping steps (wizard forms)
showStepIndicatorbooleanoptionalShow the step indicator (wizard forms)
splitDirectionEnum<'horizontal' | 'vertical'>optionalSplit orientation (split forms)
splitSizenumberoptionalPrimary split panel size, % (split forms)
splitResizablebooleanoptionalWhether the split is resizable (split forms)
drawerSideEnum<'top' | 'bottom' | 'left' | 'right'>optionalDrawer side (drawer forms)
drawerWidthstringoptional[DEPRECATED → size buckets] Drawer width, e.g. "480px". A pixel width cannot be chosen without knowing the client viewport — the renderer derives it.
modalSizeEnum<'sm' | 'default' | 'lg' | 'xl' | 'full'>optionalModal size (modal forms)
data{ provider: 'object'; object: string } | { provider: 'api'; read?: object; write?: object } | { provider: 'value'; items: any[] } | { provider: 'schema'; schemaId: string; schema?: Record<string, any> }optionalData source configuration (defaults to "object" provider)
sections{ name?: string; label?: string | Record<string, string>; description?: string; collapsible?: boolean; … }[]optional
groups{ name?: string; label?: string | Record<string, string>; description?: string; collapsible?: boolean; … }[]optional[LEGACY ALIAS → sections] Accepted for back-compat and folded onto sections at parse; sections wins when both are present. Prefer sections.
subforms{ childObject: string; relationshipField?: string; columns?: any[]; amountField?: string; … }[]optionalInline master-detail child collections
defaultSortneveroptional[REMOVED] form.defaultSort was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — nothing read it: a related list inside a form sorts by its own list view's sort. Delete the key and set the sort on the related list view instead. Run os migrate meta --from 16 to rewrite existing sources automatically.
sharing{ enabled?: boolean; publicLink?: string; password?: string; allowedDomains?: string[]; … }optionalPublic sharing configuration for this form
submitBehavior{ kind: 'thank-you'; title?: string; message?: string } | { kind: 'redirect'; url: string; delayMs?: integer } | { kind: 'continue' } | { kind: 'next-record' }optionalPost-submit behavior. On the redirect arm, url is relative-only and interpolates only declared record fields as {{record.field_name}}, URL-escaped (ruled 2026-08-11, #7496).
buttons{ submit?: object; cancel?: object; reset?: object }optionalForm action-button visibility & labels; folded onto the flat renderer props by ObjectUI ObjectForm (framework#1894 / #2998).
defaultsRecord<string, any>optionalInitial field values for create-mode forms (folded into ObjectUI ObjectForm initial values; framework#1894 / #2998).
arianeveroptional[REMOVED] form.aria was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no form renderer ever applied it, so declared ARIA attributes silently did not reach the DOM. Delete the key. The form renderer emits its own semantic markup; report gaps as renderer issues rather than per-view attribute overrides. Run os migrate meta --from 16 to rewrite existing sources automatically.

GalleryConfig

Gallery/card view configuration

Properties

PropertyTypeRequiredDescription
coverFieldstringoptionalAttachment/image field to display as card cover
coverFitEnum<'cover' | 'contain'>Image fit mode for card cover
cardSizeEnum<'small' | 'medium' | 'large'>Card size in gallery view
titleFieldstringoptionalField to display as card title
visibleFieldsstring[]optionalFields to display on card body

GanttConfig

Properties

PropertyTypeRequiredDescription
startDateFieldstringField providing the task start date
endDateFieldstringField providing the task end date
titleFieldstringField displayed as the task title
progressFieldstringoptionalField providing the task completion percentage
dependenciesFieldstringoptionalField listing the task's predecessor (dependency) record ids
colorFieldstringoptionalField that drives the bar color
parentFieldstringoptionalField holding the parent task id (builds the summary → step tree)
typeFieldstringoptionalField whose value maps to task/summary/milestone
baselineStartFieldstringoptionalBaseline (planned) start field
baselineEndFieldstringoptionalBaseline (planned) end field
groupByFieldstringoptionalField to group leaf tasks by (synthesized summary rows)
resourceViewbooleanoptionalRender a per-resource workload histogram instead of the timeline
assigneeFieldstringoptionalResource field to bucket load by (resource view)
effortFieldstringoptionalPer-task load units (resource view; default 1)
capacitynumberoptionalPer-resource capacity ceiling; loads above this flag overload
tooltipFields(string | { field: string; label?: string })[]optionalFields to surface in the hover tooltip, in display order
quickFilters{ field: string; label?: string; options?: (string | object)[] }[]optionalMulti-select filter dropdowns rendered above the chart
autoZoomToFilterbooleanoptionalWhen true (default), filtering zooms the range to the filtered tasks

GanttQuickFilter

Properties

PropertyTypeRequiredDescription
fieldstringRecord field / dot-path the dimension filters on
labelstringoptionalTrigger label (falls back to the field label)
options(string | { value: string | number; label?: string })[]optionalExplicit option override for fixed enums

GroupingConfig

Record grouping configuration

Properties

PropertyTypeRequiredDescription
fields{ field: string; order: Enum<'asc' | 'desc'>; collapsed: boolean }[]Fields to group by, in nesting order — the first entry is the outermost group and each later entry nests one level deeper (at least one field)

GroupingField

Properties

PropertyTypeRequiredDescription
fieldstringField name to group by
orderEnum<'asc' | 'desc'>Group sort order
collapsedbooleanCollapse groups by default

HttpMethodSubset

HTTP methods a view data source may request — the subset of HttpMethod without HEAD/OPTIONS.

Allowed Values

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE

HttpRequest

Properties

PropertyTypeRequiredDescription
urlstringAPI endpoint URL
methodEnum<'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'>HTTP method
headersRecord<string, string>optionalCustom HTTP headers
paramsRecord<string, any>optionalQuery parameters
bodyanyoptionalRequest body for POST/PUT/PATCH

KanbanConfig

Properties

PropertyTypeRequiredDescription
groupByFieldstringField to group columns by (usually status/select)
summarizeFieldstringoptionalField to sum at top of column (e.g. amount)
columnsstring[]Fields to show on cards

ListChartConfig

List chart view configuration

Properties

PropertyTypeRequiredDescription
chartTypeEnum<'bar' | 'line' | 'pie' | 'area' | 'scatter'>Chart visualisation type
datasetstringDataset name to bind (ADR-0021)
dimensionsstring[]optionalDimension names — X/group/split
valuesstring[]Measure names — Y (at least one)

ListColumn

Properties

PropertyTypeRequiredDescription
fieldstringField name (snake_case)
labelstring | Record<string, string>optionalDisplay label override
widthnumberoptionalColumn width in pixels
alignEnum<'left' | 'center' | 'right'>optionalText alignment
hiddenbooleanoptionalHide column by default
sortablebooleanoptionalAllow sorting by this column
resizablebooleanoptionalAllow resizing this column
wrapbooleanoptionalAllow text wrapping
typestringoptionalRenderer type override (e.g., "currency", "date")
pinnedEnum<'left' | 'right'>optionalPin/freeze column to left or right side
summaryEnum<'none' | 'count' | 'count_empty' | 'count_filled' | 'count_unique' | 'percent_empty' | 'percent_filled' | 'sum' | 'avg' | 'min' | 'max'> | { type: Enum<'none' | 'count' | 'count_empty' | 'count_filled' | 'count_unique' | … +6 more>; field?: string }optionalFooter aggregation for this column — the function alone, or { type, field } to aggregate another field
prefix{ field: string; type: Enum<'badge' | 'text'> }optionalField rendered inline before this cell value
linkbooleanoptionalFunctions as the primary navigation link (triggers View navigation)
actionstringoptionalRegistered Action ID to execute when clicked

ListView

Properties

PropertyTypeRequiredDescription
namestringoptionalInternal view name (lowercase snake_case)
labelstring | Record<string, string>optionalDisplay label — the default-language string, or an inline locale map ({ en, "zh-CN" }) resolved at render time
typeEnum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>optional
data{ provider: 'object'; object: string } | { provider: 'api'; read?: object; write?: object } | { provider: 'value'; items: any[] } | { provider: 'schema'; schemaId: string; schema?: Record<string, any> }optionalData source configuration (defaults to "object" provider)
columnsstring[] | { field: string; label?: string | Record<string, string>; width?: number; align?: Enum<'left' | 'center' | 'right'>; … }[]Fields to display as columns
filter{ field: string; operator?: Enum<'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | … +14 more>; value?: string | number | boolean | null | (string | number)[] }[]optionalFilter criteria (JSON Rules)
sortstring | { field: string; order: Enum<'asc' | 'desc'> }[]optional
searchableFieldsstring[]optionalFields enabled for search
filterableFieldsstring[]optionalLegacy shorthand for userFilters.fields — bare field names enabled for end-user filtering. Prefer userFilters
userFilters{ element?: Enum<'dropdown' | 'tabs' | 'toggle'>; fields?: object[]; tabs?: object[]; showAllRecords?: boolean; … }optionalEnd-user quick-filter bar: dropdown/toggle fields or tab presets. Omit to let the renderer derive filters from select/boolean fields
resizablebooleanoptionalEnable column resizing
stripedbooleanoptionalStriped row styling
borderedbooleanoptionalShow borders
compactToolbarbooleanoptionalCollapse Group/Color/Density/Hide-fields into a single View settings popover
selection{ type?: Enum<'none' | 'single' | 'multiple'> }optionalRow selection configuration
navigation{ mode?: Enum<'page' | 'drawer' | 'modal' | 'split' | 'popover' | 'new_window' | 'none'>; view?: string; preventNavigation?: boolean; openNewTab?: boolean; … }optionalConfiguration for item click navigation (page, drawer, modal, etc.)
pagination{ pageSize?: integer; pageSizeOptions?: integer[] }optionalPagination configuration
kanban{ groupByField: string; summarizeField?: string; columns: string[] }optionalKanban-board configuration — applies when the view renders as a kanban layout
calendar{ startDateField: string; endDateField?: string; titleField: string; colorField?: string }optionalCalendar configuration — applies when the view renders as a calendar layout
gantt{ startDateField: string; endDateField: string; titleField: string; progressField?: string; … } & Record<string, any>optionalGantt-timeline configuration — applies when the view renders as a gantt layout
gallery{ coverField?: string; coverFit?: Enum<'cover' | 'contain'>; cardSize?: Enum<'small' | 'medium' | 'large'>; titleField?: string; … }optionalGallery/card view configuration
timeline{ startDateField: string; endDateField?: string; titleField: string; groupByField?: string; … }optionalTimeline view configuration
chart{ chartType?: Enum<'bar' | 'line' | 'pie' | 'area' | 'scatter'>; dataset: string; dimensions?: string[]; values: string[] }optionalList chart view configuration
tree{ parentField?: string; labelField?: string; fields?: string[]; defaultExpandedDepth?: integer } & Record<string, any>optionalTree/hierarchy configuration — applies when the view renders as a tree layout
descriptionstring | Record<string, string>optionalView description for documentation/tooltips
sharing{ type?: Enum<'personal' | 'collaborative'>; lockedBy?: string }optionalView sharing and access configuration
rowHeightEnum<'compact' | 'short' | 'medium' | 'tall' | 'extra_tall'>optionalRow height / density setting
grouping{ fields: object[] }optionalGroup records by one or more fields
rowColor{ field: string; colors?: Record<string, string> }optionalColor rows based on field value
hiddenFieldsstring[]optionalFields to hide in this specific view
fieldOrderstring[]optionalExplicit field display order for this view
rowActionsstring[]optionalActions available for individual row items
bulkActionsstring[]optionalActions available when multiple rows are selected
bulkActionDefs{ name: string; label?: string; icon?: string; variant?: Enum<'primary' | 'secondary' | 'danger' | 'ghost' | 'outline'>; … }[]optionalRich bulk action definitions (schema-driven, executed via BulkActionDialog). Use a def for a mass data-plane mutation ('update' with a patch / 'delete') that no action expresses, or for an operation: 'custom' + execution: 'aggregate' entry (objectui#3139) that dispatches the action it NAMES once for the whole selection — the renderer injects params._selectedIds: string[] (read that on the server, not recordId) so a single call can produce one aggregate artifact (zip of QR codes, merged PDF, batch print). Aggregate results are all-or-nothing: a handler that cannot cover the whole selection must reject, and per-row retry is replaced by re-running the action. batchSize does not apply (the call is never chunked); set maxRecords on defs whose server work is expensive. For the PER-RECORD dispatch use bulkActions: ['<name>'] instead — the bare-string form, promoted with the action's own label, params and visible; a 'custom' def without execution: 'aggregate' has no dispatcher and is refused at parse time (#4457). Toolbar url/api actions can also interpolate the current selection via ${ctx.selection.ids} / ${ctx.selection.count}.
virtualScrollbooleanoptionalEnable virtual scrolling for large datasets
conditionalFormatting{ condition: string | object; style: Record<string, string> }[]optionalConditional formatting rules for list rows
inlineEditbooleanoptionalAllow inline editing of records directly in the list view
exportOptionsEnum<'csv' | 'xlsx' | 'pdf' | 'json'>[]optionalAvailable export format options
userActions{ sort?: boolean; search?: boolean; filter?: boolean; refresh?: boolean; … }optionalUser action toggles for the view toolbar
appearance{ showDescription?: boolean; allowedVisualizations?: Enum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>[] }optionalAppearance and visualization configuration
tabs{ name: string; label?: string | Record<string, string>; icon?: string; view?: string; … }[]optionalTab definitions for multi-tab view interface
addRecord{ enabled?: boolean; position?: Enum<'top' | 'bottom' | 'both'>; mode?: Enum<'inline' | 'form' | 'modal'>; formView?: string }optionalAdd record entry point configuration
showRecordCountbooleanoptionalShow record count at the bottom of the list
allowPrintingbooleanoptionalAllow users to print the view
emptyState{ title?: string | Record<string, string>; message?: string | Record<string, string>; icon?: string }optionalEmpty state configuration when no records found
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes for the list view
responsiveneveroptional[REMOVED] view.responsive was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer ever read it; the grid is responsive by its own layout rules. Delete the key. Run os migrate meta --from 16 to rewrite existing sources automatically.
performanceneveroptional[REMOVED] view.performance was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer or runtime read it; list-view performance tuning was never implemented. Delete the key. Run os migrate meta --from 16 to rewrite existing sources automatically.

Properties

PropertyTypeRequiredDescription
modeEnum<'page' | 'drawer' | 'modal' | 'split' | 'popover' | 'new_window' | 'none'>
viewstringoptionalName of the form view to use for details (e.g. "summary_view", "edit_form")
preventNavigationbooleanDisable standard navigation entirely
openNewTabbooleanForce open in new tab (applies to page mode)
sizeEnum<'auto' | 'sm' | 'md' | 'lg' | 'xl' | 'full'>[#2578] Overlay size bucket for drawer/modal detail: 'auto' (default — renderer derives from field count + viewport; AI writes nothing) or a coarse override sm/md/lg/xl/full. Prefer this over the pixel width; page mode ignores it.
widthstring | numberoptional[DEPRECATED → size] Pixel/percent width of the drawer/modal (e.g. "600px"). A pixel width cannot be chosen at authoring time without knowing the client viewport — use the size bucket.

Allowed Values

  • page
  • drawer
  • modal
  • split
  • popover
  • new_window
  • none

ObjectListView

Properties

PropertyTypeRequiredDescription
namestringoptionalInternal view name (lowercase snake_case)
labelstring | Record<string, string>optionalDisplay label — the default-language string, or an inline locale map ({ en, "zh-CN" }) resolved at render time
typeEnum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>optional
data{ provider: 'object'; object: string } | { provider: 'api'; read?: object; write?: object } | { provider: 'value'; items: any[] } | { provider: 'schema'; schemaId: string; schema?: Record<string, any> }optionalData source configuration (defaults to "object" provider)
columnsstring[] | { field: string; label?: string | Record<string, string>; width?: number; align?: Enum<'left' | 'center' | 'right'>; … }[]Fields to display as columns
filter{ field: string; operator?: Enum<'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | … +14 more>; value?: string | number | boolean | null | (string | number)[] }[]optionalFilter criteria (JSON Rules)
sortstring | { field: string; order: Enum<'asc' | 'desc'> }[]optional
searchableFieldsstring[]optionalFields enabled for search
filterableFieldsstring[]optionalLegacy shorthand for userFilters.fields — bare field names enabled for end-user filtering. Prefer userFilters
resizablebooleanoptionalEnable column resizing
stripedbooleanoptionalStriped row styling
borderedbooleanoptionalShow borders
compactToolbarbooleanoptionalCollapse Group/Color/Density/Hide-fields into a single View settings popover
selection{ type?: Enum<'none' | 'single' | 'multiple'> }optionalRow selection configuration
navigation{ mode?: Enum<'page' | 'drawer' | 'modal' | 'split' | 'popover' | 'new_window' | 'none'>; view?: string; preventNavigation?: boolean; openNewTab?: boolean; … }optionalConfiguration for item click navigation (page, drawer, modal, etc.)
pagination{ pageSize?: integer; pageSizeOptions?: integer[] }optionalPagination configuration
kanban{ groupByField: string; summarizeField?: string; columns: string[] }optionalKanban-board configuration — applies when the view renders as a kanban layout
calendar{ startDateField: string; endDateField?: string; titleField: string; colorField?: string }optionalCalendar configuration — applies when the view renders as a calendar layout
gantt{ startDateField: string; endDateField: string; titleField: string; progressField?: string; … } & Record<string, any>optionalGantt-timeline configuration — applies when the view renders as a gantt layout
gallery{ coverField?: string; coverFit?: Enum<'cover' | 'contain'>; cardSize?: Enum<'small' | 'medium' | 'large'>; titleField?: string; … }optionalGallery/card view configuration
timeline{ startDateField: string; endDateField?: string; titleField: string; groupByField?: string; … }optionalTimeline view configuration
chart{ chartType?: Enum<'bar' | 'line' | 'pie' | 'area' | 'scatter'>; dataset: string; dimensions?: string[]; values: string[] }optionalList chart view configuration
tree{ parentField?: string; labelField?: string; fields?: string[]; defaultExpandedDepth?: integer } & Record<string, any>optionalTree/hierarchy configuration — applies when the view renders as a tree layout
descriptionstring | Record<string, string>optionalView description for documentation/tooltips
sharing{ type?: Enum<'personal' | 'collaborative'>; lockedBy?: string }optionalView sharing and access configuration
rowHeightEnum<'compact' | 'short' | 'medium' | 'tall' | 'extra_tall'>optionalRow height / density setting
grouping{ fields: object[] }optionalGroup records by one or more fields
rowColor{ field: string; colors?: Record<string, string> }optionalColor rows based on field value
hiddenFieldsstring[]optionalFields to hide in this specific view
fieldOrderstring[]optionalExplicit field display order for this view
rowActionsstring[]optionalActions available for individual row items
bulkActionsstring[]optionalActions available when multiple rows are selected
bulkActionDefs{ name: string; label?: string; icon?: string; variant?: Enum<'primary' | 'secondary' | 'danger' | 'ghost' | 'outline'>; … }[]optionalRich bulk action definitions (schema-driven, executed via BulkActionDialog). Use a def for a mass data-plane mutation ('update' with a patch / 'delete') that no action expresses, or for an operation: 'custom' + execution: 'aggregate' entry (objectui#3139) that dispatches the action it NAMES once for the whole selection — the renderer injects params._selectedIds: string[] (read that on the server, not recordId) so a single call can produce one aggregate artifact (zip of QR codes, merged PDF, batch print). Aggregate results are all-or-nothing: a handler that cannot cover the whole selection must reject, and per-row retry is replaced by re-running the action. batchSize does not apply (the call is never chunked); set maxRecords on defs whose server work is expensive. For the PER-RECORD dispatch use bulkActions: ['<name>'] instead — the bare-string form, promoted with the action's own label, params and visible; a 'custom' def without execution: 'aggregate' has no dispatcher and is refused at parse time (#4457). Toolbar url/api actions can also interpolate the current selection via ${ctx.selection.ids} / ${ctx.selection.count}.
virtualScrollbooleanoptionalEnable virtual scrolling for large datasets
conditionalFormatting{ condition: string | object; style: Record<string, string> }[]optionalConditional formatting rules for list rows
inlineEditbooleanoptionalAllow inline editing of records directly in the list view
exportOptionsEnum<'csv' | 'xlsx' | 'pdf' | 'json'>[]optionalAvailable export format options
userActions{ sort?: boolean; search?: boolean; filter?: boolean; refresh?: boolean; … }optionalUser action toggles for the view toolbar
appearance{ showDescription?: boolean; allowedVisualizations?: Enum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>[] }optionalAppearance and visualization configuration
tabs{ name: string; label?: string | Record<string, string>; icon?: string; view?: string; … }[]optionalTab definitions for multi-tab view interface
addRecord{ enabled?: boolean; position?: Enum<'top' | 'bottom' | 'both'>; mode?: Enum<'inline' | 'form' | 'modal'>; formView?: string }optionalAdd record entry point configuration
showRecordCountbooleanoptionalShow record count at the bottom of the list
allowPrintingbooleanoptionalAllow users to print the view
emptyState{ title?: string | Record<string, string>; message?: string | Record<string, string>; icon?: string }optionalEmpty state configuration when no records found
aria{ ariaLabel?: string | Record<string, string>; ariaDescribedBy?: string; role?: string }optionalARIA accessibility attributes for the list view
responsiveneveroptional[REMOVED] view.responsive was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer ever read it; the grid is responsive by its own layout rules. Delete the key. Run os migrate meta --from 16 to rewrite existing sources automatically.
performanceneveroptional[REMOVED] view.performance was removed in @objectstack/spec 17.0.0 (#3896 audit close-out) — no renderer or runtime read it; list-view performance tuning was never implemented. Delete the key. Run os migrate meta --from 16 to rewrite existing sources automatically.
userFilters{ element?: Enum<'dropdown' | 'toggle'>; fields?: object[] }optional

ObjectUserFilters

Properties

PropertyTypeRequiredDescription
elementEnum<'dropdown' | 'toggle'>Filter control style on object views: "dropdown" (per-field value chips). "toggle" is deprecated. "tabs" is page-only — use listViews for named presets.
fields{ field: string; label?: string | Record<string, string>; type?: Enum<'select' | 'multi-select' | 'boolean' | 'date-range' | 'text'>; options?: object[]; … }[]optionalFields exposed as quick filters (dropdown/toggle elements)

PaginationConfig

Properties

PropertyTypeRequiredDescription
pageSizeintegerNumber of records per page
pageSizeOptionsinteger[]optionalAvailable page size options

RowColorConfig

Row color configuration based on field values

Properties

PropertyTypeRequiredDescription
fieldstringField to derive color from (typically a select/status field)
colorsRecord<string, string>optionalMap of field value to color (hex/token)

RowHeight

Row height / density setting for list view

Allowed Values

  • compact
  • short
  • medium
  • tall
  • extra_tall

SelectionConfig

Properties

PropertyTypeRequiredDescription
typeEnum<'none' | 'single' | 'multiple'>Selection mode

TimelineConfig

Timeline view configuration

Properties

PropertyTypeRequiredDescription
startDateFieldstringField for timeline item start date
endDateFieldstringoptionalField for timeline item end date
titleFieldstringField to display as timeline item title
groupByFieldstringoptionalField to group timeline rows
colorFieldstringoptionalField to determine item color
scaleEnum<'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'>Default timeline scale

TreeConfig

Properties

PropertyTypeRequiredDescription
parentFieldstringoptionalSingle-parent pointer field (auto-detected from the object schema when omitted)
labelFieldstringoptionalField rendered indented in the first column (defaults to "name")
fieldsstring[]optionalAdditional fields rendered as flat columns alongside the label
defaultExpandedDepthintegeroptionalInitial expansion depth (0 = roots only; omit = expand all)

UserActionsConfig

User action toggles for the view toolbar

Properties

PropertyTypeRequiredDescription
sortbooleanAllow users to sort records
searchbooleanAllow users to search records
filterbooleanAllow users to filter records
refreshbooleanAllow users to reload the view data from the backend without a full page reload
rowHeightbooleanAllow users to toggle row height/density
addRecordFormbooleanAdd records through a form instead of inline
editInlinebooleanAllow users to edit records inline — click a cell to edit it with the field's type-aware widget (the same control the form uses). Off by default: the list is read-only unless the author opts in.
buttonsstring[]optionalCustom action button IDs to show in the toolbar

UserFilterField

Quick-filter field configuration

Properties

PropertyTypeRequiredDescription
fieldstringField name on the source object (must exist — checked by reference diagnostics)
labelstring | Record<string, string>optionalDisplay label override (defaults to the field label)
typeEnum<'select' | 'multi-select' | 'boolean' | 'date-range' | 'text'>optionalFilter control type. Omit to infer from the field definition
options{ value: string | number | boolean; label: string | Record<string, string>; color?: string }[]optionalStatic options. Omit to derive from the field definition (select options / lookup records)
showCountbooleanoptionalShow per-option record counts
defaultValues(string | number | boolean)[]optionalPre-selected values when the view loads

UserFilters

End-user quick-filter configuration (Airtable "User filters" parity)

Properties

PropertyTypeRequiredDescription
elementEnum<'dropdown' | 'tabs' | 'toggle'>Filter control style: "dropdown" (per-field value selectors) or "tabs" (named presets). "toggle" is deprecated.
fields{ field: string; label?: string | Record<string, string>; type?: Enum<'select' | 'multi-select' | 'boolean' | 'date-range' | 'text'>; options?: object[]; … }[]optionalFields exposed as quick filters (dropdown/toggle elements)
tabs{ name: string; label?: string | Record<string, string>; icon?: string; view?: string; … }[]optionalNamed filter presets rendered as tabs (tabs element). Reuses ViewTabSchema
showAllRecordsbooleanoptionalShow an "All records" tab before the presets (tabs element)
allowAddTabbooleanoptionalLet end users add their own tab after the presets (tabs element): the affordance asks for a name and snapshots the filters currently applied as a new tab. SESSION-SCOPED — an added tab lives only for the current mount, is never written back as metadata (ADR-0047), and carries a remove control the authored presets do not. Page lists only — object views use listViews for named presets

View

Properties

PropertyTypeRequiredDescription
namestringoptionalItem name — supplied by the metadata door; for an object-scoped container it is the object name.
labelstring | Record<string, string>optionalHuman-readable label shown in metadata lists.
objectstringoptionalObject this container binds to — how a stack-level views: [...] entry says which object its views belong to; read by getViewsByObject() / GET /meta/view?object=.
list{ name?: string; label?: string | Record<string, string>; type?: Enum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>; data?: object | … +3 more; … }optional
form{ type?: Enum<'simple' | 'tabbed' | 'wizard' | 'split' | 'drawer' | 'modal'>; layout?: Enum<'vertical' | 'horizontal' | 'inline' | 'grid'>; columns?: integer; title?: string; … }optional
listViewsRecord<string, { name?: string; label?: string | Record<string, string>; type?: Enum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>; data?: object | … +3 more; … }>optionalAdditional named list views (views mode — dropdown userFilters allowed, no tabs; ADR-0047)
formViewsRecord<string, { type?: Enum<'simple' | 'tabbed' | 'wizard' | 'split' | 'drawer' | 'modal'>; layout?: Enum<'vertical' | 'horizontal' | 'inline' | 'grid'>; columns?: integer; title?: string; … }>optionalAdditional named form views
protection{ lock: Enum<'none' | 'no-overlay' | 'no-delete' | 'full'>; reason: string; docsUrl?: string }optionalPackage author protection block — lock policy for this view.
_lockEnum<'none' | 'no-overlay' | 'no-delete' | 'full'>optionalItem-level lock — controls overlay & delete (ADR-0010).
_lockReasonstringoptionalHuman-readable reason shown when a write is refused by _lock.
_lockSourceEnum<'artifact' | 'package' | 'env-forced'>optionalLayer that set _lock (artifact | package | env-forced).
_provenanceEnum<'package' | 'org' | 'env-forced'>optionalOrigin of the item (package | org | env-forced).
_packageIdstringoptionalOwning package machine id.
_packageVersionstringoptionalOwning package version.
_lockDocsUrlstringoptionalOptional documentation link surfaced next to _lockReason.

ViewData

Union Options

This schema accepts one of the following structures:

Option 1

Properties

PropertyTypeRequiredDescription
provider'object'
objectstringTarget object name

Option 2

Properties

PropertyTypeRequiredDescription
provider'api'
read{ url: string; method: Enum<'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'>; headers?: Record<string, string>; params?: Record<string, any>; … }optionalConfiguration for fetching data
write{ url: string; method: Enum<'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'>; headers?: Record<string, string>; params?: Record<string, any>; … }optionalConfiguration for submitting data (for forms/editable tables)

Option 3

Properties

PropertyTypeRequiredDescription
provider'value'
itemsany[]Static data array

Option 4

Properties

PropertyTypeRequiredDescription
provider'schema'
schemaIdstringSchema identifier — typically the metadata type name
schemaRecord<string, any>optionalInline JSON Schema (Draft 2020-12). Optional when schemaId is resolvable.


ViewFilterRule

View filter rule

Properties

PropertyTypeRequiredDescription
fieldstringField name to filter on
operatorEnum<'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | 'ends_with' | 'greater_than' | 'less_than' | 'greater_than_or_equal' | … +10 more>Filter operator
valuestring | number | boolean | null | (string | number)[]optionalFilter value. The accepted SHAPE depends on the operator: in / not_in take an array (any length, including []), between takes exactly [min, max], every other operator takes a scalar. The unary operators (is_empty / is_not_empty / is_null / is_not_null) take their direction from the operator name and ignore this key.

Allowed Values: ViewFilterRule.operator

  • equals
  • not_equals
  • contains
  • not_contains
  • starts_with
  • ends_with
  • greater_than
  • less_than
  • greater_than_or_equal
  • less_than_or_equal
  • in
  • not_in
  • is_empty
  • is_not_empty
  • is_null
  • is_not_null
  • before
  • after
  • between

ViewItem

Union Options

This schema accepts one of the following structures:

Option 1

Properties

PropertyTypeRequiredDescription
viewKind'list'
config{ name?: string; label?: string | Record<string, string>; type?: Enum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>; data?: object | … +3 more; … }List-family view configuration.
namestringGlobally-unique view id, <object>.<viewKey>.
objectstringBound object name — the foreign key used to aggregate views.
labelstring | Record<string, string>optionalDisplay label (supports i18n).
isDefaultbooleanoptionalWhether this is the object's default view in the switcher.
orderintegeroptionalSort order within the object's view switcher / left rail.
scopeEnum<'package' | 'shared' | 'personal'>optionalIdentity layer (defaults to package for source-loaded views).
ownerstringoptionalOwner user id — set when scope is personal.
hiddenbooleanoptionalHidden from the switcher (per-user / per-org declutter).
protection{ lock: Enum<'none' | 'no-overlay' | 'no-delete' | 'full'>; reason: string; docsUrl?: string }optionalPackage author protection block — lock policy for this view.
_lockEnum<'none' | 'no-overlay' | 'no-delete' | 'full'>optionalItem-level lock — controls overlay & delete (ADR-0010).
_lockReasonstringoptionalHuman-readable reason shown when a write is refused by _lock.
_lockSourceEnum<'artifact' | 'package' | 'env-forced'>optionalLayer that set _lock (artifact | package | env-forced).
_provenanceEnum<'package' | 'org' | 'env-forced'>optionalOrigin of the item (package | org | env-forced).
_packageIdstringoptionalOwning package machine id.
_packageVersionstringoptionalOwning package version.
_lockDocsUrlstringoptionalOptional documentation link surfaced next to _lockReason.

Option 2

Properties

PropertyTypeRequiredDescription
viewKind'form'
config{ type?: Enum<'simple' | 'tabbed' | 'wizard' | 'split' | 'drawer' | 'modal'>; layout?: Enum<'vertical' | 'horizontal' | 'inline' | 'grid'>; columns?: integer; title?: string; … }Form view configuration.
namestringGlobally-unique view id, <object>.<viewKey>.
objectstringBound object name — the foreign key used to aggregate views.
labelstring | Record<string, string>optionalDisplay label (supports i18n).
isDefaultbooleanoptionalWhether this is the object's default view in the switcher.
orderintegeroptionalSort order within the object's view switcher / left rail.
scopeEnum<'package' | 'shared' | 'personal'>optionalIdentity layer (defaults to package for source-loaded views).
ownerstringoptionalOwner user id — set when scope is personal.
hiddenbooleanoptionalHidden from the switcher (per-user / per-org declutter).
protection{ lock: Enum<'none' | 'no-overlay' | 'no-delete' | 'full'>; reason: string; docsUrl?: string }optionalPackage author protection block — lock policy for this view.
_lockEnum<'none' | 'no-overlay' | 'no-delete' | 'full'>optionalItem-level lock — controls overlay & delete (ADR-0010).
_lockReasonstringoptionalHuman-readable reason shown when a write is refused by _lock.
_lockSourceEnum<'artifact' | 'package' | 'env-forced'>optionalLayer that set _lock (artifact | package | env-forced).
_provenanceEnum<'package' | 'org' | 'env-forced'>optionalOrigin of the item (package | org | env-forced).
_packageIdstringoptionalOwning package machine id.
_packageVersionstringoptionalOwning package version.
_lockDocsUrlstringoptionalOptional documentation link surfaced next to _lockReason.


ViewItemName

Globally-unique view id, <object>.<viewKey>.

Type: string


ViewItemWire

Union Options

This schema accepts one of the following structures:

Option 1

Properties

PropertyTypeRequiredDescription
viewKind'list'
config{ name?: string; label?: string | Record<string, string>; type?: Enum<'grid' | 'kanban' | 'gallery' | 'calendar' | 'timeline' | 'gantt' | 'map' | 'chart' | 'tree'>; data?: object | … +3 more; … }List-family view configuration.
namestringGlobally-unique view id, <object>.<viewKey>.
objectstringBound object name — the foreign key used to aggregate views.
labelstring | Record<string, string>optionalDisplay label (supports i18n).
isDefaultbooleanoptionalWhether this is the object's default view in the switcher.
orderintegeroptionalSort order within the object's view switcher / left rail.
scopeEnum<'package' | 'shared' | 'personal'>optionalIdentity layer (defaults to package for source-loaded views).
ownerstringoptionalOwner user id — set when scope is personal.
hiddenbooleanoptionalHidden from the switcher (per-user / per-org declutter).
protection{ lock: Enum<'none' | 'no-overlay' | 'no-delete' | 'full'>; reason: string; docsUrl?: string }optionalPackage author protection block — lock policy for this view.
_lockEnum<'none' | 'no-overlay' | 'no-delete' | 'full'>optionalItem-level lock — controls overlay & delete (ADR-0010).
_lockReasonstringoptionalHuman-readable reason shown when a write is refused by _lock.
_lockSourceEnum<'artifact' | 'package' | 'env-forced'>optionalLayer that set _lock (artifact | package | env-forced).
_provenanceEnum<'package' | 'org' | 'env-forced'>optionalOrigin of the item (package | org | env-forced).
_packageIdstringoptionalOwning package machine id.
_packageVersionstringoptionalOwning package version.
_lockDocsUrlstringoptionalOptional documentation link surfaced next to _lockReason.
isPinnedbooleanoptionalStudio round-trip: view pinned in the switcher (per-user state, written by the console — not authored).
sortOrderintegeroptionalStudio round-trip: position within the switcher (per-user state, written by the console — not authored).

Option 2

Properties

PropertyTypeRequiredDescription
viewKind'form'
config{ type?: Enum<'simple' | 'tabbed' | 'wizard' | 'split' | 'drawer' | 'modal'>; layout?: Enum<'vertical' | 'horizontal' | 'inline' | 'grid'>; columns?: integer; title?: string; … }Form view configuration.
namestringGlobally-unique view id, <object>.<viewKey>.
objectstringBound object name — the foreign key used to aggregate views.
labelstring | Record<string, string>optionalDisplay label (supports i18n).
isDefaultbooleanoptionalWhether this is the object's default view in the switcher.
orderintegeroptionalSort order within the object's view switcher / left rail.
scopeEnum<'package' | 'shared' | 'personal'>optionalIdentity layer (defaults to package for source-loaded views).
ownerstringoptionalOwner user id — set when scope is personal.
hiddenbooleanoptionalHidden from the switcher (per-user / per-org declutter).
protection{ lock: Enum<'none' | 'no-overlay' | 'no-delete' | 'full'>; reason: string; docsUrl?: string }optionalPackage author protection block — lock policy for this view.
_lockEnum<'none' | 'no-overlay' | 'no-delete' | 'full'>optionalItem-level lock — controls overlay & delete (ADR-0010).
_lockReasonstringoptionalHuman-readable reason shown when a write is refused by _lock.
_lockSourceEnum<'artifact' | 'package' | 'env-forced'>optionalLayer that set _lock (artifact | package | env-forced).
_provenanceEnum<'package' | 'org' | 'env-forced'>optionalOrigin of the item (package | org | env-forced).
_packageIdstringoptionalOwning package machine id.
_packageVersionstringoptionalOwning package version.
_lockDocsUrlstringoptionalOptional documentation link surfaced next to _lockReason.
isPinnedbooleanoptionalStudio round-trip: view pinned in the switcher (per-user state, written by the console — not authored).
sortOrderintegeroptionalStudio round-trip: position within the switcher (per-user state, written by the console — not authored).


ViewKind

Whether config is a ListView (list family) or a FormView.

Allowed Values

  • list
  • form

ViewScope

View identity layer: package | shared | personal.

Allowed Values

  • package
  • shared
  • personal

ViewSharing

View sharing and access configuration

Properties

PropertyTypeRequiredDescription
typeEnum<'personal' | 'collaborative'>View ownership type
lockedBystringoptionalUser who locked the view configuration

ViewTab

Tab configuration for multi-tab view interface

Properties

PropertyTypeRequiredDescription
namestringTab identifier (snake_case)
labelstring | Record<string, string>optionalDisplay label
iconstringoptionalTab icon name
viewstringoptionalReferenced list view name from listViews
filter{ field: string; operator: Enum<'equals' | 'not_equals' | 'contains' | 'not_contains' | 'starts_with' | … +14 more>; value?: string | number | boolean | null | (string | number)[] }[]optionalTab-specific filter criteria
orderintegeroptionalTab display order
pinnedbooleanPin tab (cannot be removed by users)
isDefaultbooleanSet as the default active tab
visiblebooleanTab visibility

VisualizationType

Visualization type that users can switch to

Allowed Values

  • grid
  • kanban
  • gallery
  • calendar
  • timeline
  • gantt
  • map
  • chart
  • tree

On this page