defineView() to ship pre-configured views with your app — typically a default index view for each custom object you create.
src/views/example-view.ts
Key points
objectUniversalIdentifierspecifies which object this view applies to. It can be a custom object you defined or a standard Twenty object.keydetermines the view type —ViewKey.INDEXis the main list view for the object.fieldscontrols which columns appear and in what order. Each field references afieldMetadataUniversalIdentifier.- You can also declare
filters,filterGroups,groups, andfieldGroupsfor advanced configurations. positioncontrols ordering when multiple views exist for the same object.
Filters
A view can ship with pre-applied filters. Each filter has three coordinates: the field being filtered, the operand (how to compare), and the value (what to compare against). All three must line up — using an operand that doesn’t apply to a field type will be rejected at sync time.Supported operands per field type
| Field type | Supported operands |
|---|---|
TEXT, EMAILS, FULL_NAME, ADDRESS, LINKS, PHONES, RAW_JSON, FILES, ACTOR, ARRAY | CONTAINS, DOES_NOT_CONTAIN, IS_EMPTY, IS_NOT_EMPTY |
ACTOR.source, ACTOR.workspaceMemberId | IS, IS_NOT, IS_EMPTY, IS_NOT_EMPTY |
SELECT | IS, IS_NOT, IS_EMPTY, IS_NOT_EMPTY |
MULTI_SELECT | CONTAINS, DOES_NOT_CONTAIN, IS_EMPTY, IS_NOT_EMPTY |
RELATION | IS, IS_NOT, IS_EMPTY, IS_NOT_EMPTY |
NUMBER | IS, IS_NOT, GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL, IS_EMPTY, IS_NOT_EMPTY |
RATING | IS, GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL, IS_EMPTY, IS_NOT_EMPTY |
CURRENCY, CURRENCY.amountMicros | GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL, IS, IS_NOT, IS_EMPTY, IS_NOT_EMPTY |
CURRENCY.currencyCode | IS, IS_NOT, IS_EMPTY, IS_NOT_EMPTY |
DATE, DATE_TIME | IS, IS_RELATIVE, IS_IN_PAST, IS_IN_FUTURE, IS_TODAY, IS_BEFORE, IS_AFTER, IS_EMPTY, IS_NOT_EMPTY |
BOOLEAN | IS |
UUID | IS, IS_NOT, IS_EMPTY, IS_NOT_EMPTY |
TS_VECTOR | VECTOR_SEARCH |
Field types with similar names can use entirely different operands —SELECTandMULTI_SELECTbeing a common case.
Value shape per operand
Thevalue field is always a JSON-serializable value, but its expected shape depends on the operand:
| Operand family | Value shape | Example |
|---|---|---|
IS, IS_NOT on SELECT | array of option keys (strings) | ['ACTIVE', 'PENDING'] |
CONTAINS, DOES_NOT_CONTAIN on MULTI_SELECT | array of option keys (strings) | ['TAG_A'] |
IS, IS_NOT on RELATION | array of record IDs (uuids) | ['c5a1...'] |
CONTAINS, DOES_NOT_CONTAIN on text-like fields | string | 'acme' |
IS, IS_NOT on NUMBER | string (the value) | '5' |
IS on RATING / UUID | string (the value) | '5' |
GREATER_THAN_OR_EQUAL, LESS_THAN_OR_EQUAL | string (the bound) | '10' |
IS, IS_BEFORE, IS_AFTER on DATE / DATE_TIME | ISO 8601 string | '2025-01-01T00:00:00Z' |
IS_EMPTY, IS_NOT_EMPTY | empty string | '' |
IS on BOOLEAN | 'true' or 'false' | 'true' |
How views show up in the UI
A view by itself isn’t reachable from the sidebar. To make it appear there, pair it with a navigation menu item of typeVIEW that points at the view’s universalIdentifier. That’s the canonical pattern: every custom object typically ships a default view + a sidebar entry that opens it.