Field Types¶
Field Types describe what each Field on a Resource stores.
When you add a Field to a Resource, you choose one of these types. Diagonal uses the type to validate input, render the right control on pages, and tell workflows how to read and write the value.
Choosing a type
Pick the narrowest type that fits the value. A clean type set keeps validation strict, pages predictable, and workflow logic simple.
Quick reference¶
| Field type | What it stores | Searchable | Unique |
|---|---|---|---|
| Text | Free-form string | Yes | Yes |
| Email address | Yes | Yes | |
| Phone | Phone number | Yes | Yes |
| Password | Hashed credential | No | No |
| Uuid | UUID identifier | No | Yes |
| Color | Color value | No | No |
| Timezone | IANA timezone | No | No |
| Number | Numeric value | No | Yes |
| Money | Amount and currency | No | No |
| Boolean | True or false | No | No |
| Date | Calendar date | No | Yes |
| Time | Time of day | No | No |
| Datetime | Date and time | No | No |
| Event Schedule | Event start/end, all-day state, and recurrence | No | No |
| Recurrence | Repeating schedule rule inside an Event Schedule | No | No |
| Regular Hours | Usual weekly open hours, with changes from a date | No | No |
| Content | Rich text document | No | No |
| Event Schedule | Structured event timing | No | No |
| File ID | Uploaded File reference | No | No |
| Dictionary | Keyed object | No | No |
| List | Ordered list of items | No | No |
| Liquid | Liquid template source | No | No |
| Location | Structured address/location | No | No |
| Markdown | Markdown source | No | No |
| Relation | Link to another Resource | No | No |
| Select | One configured option | No | No |
| URL | Web address | No | No |
Text and identifiers¶
Use these for human-readable strings, contact details, and stable identifiers.
Text¶
A free-form string. Use this for names, titles, descriptions, notes, slugs, and other plain or formatted text fields.
| Setting | Why it matters |
|---|---|
| Searchable | Include this field when users search records. |
| Unique | Prevent duplicate values across records. |
Email¶
An email address. Same options as Text, with built-in email validation. Used by Authenticatable and Notifiable Capabilities to identify and contact users.
Phone¶
A phone number. Validated as a phone string and rendered with a phone-friendly input on pages.
Password¶
A password credential. Stored hashed and never displayed back in System Admin. Pair with Email on an Authenticatable Resource to enable login.
Uuid¶
A UUID identifier. Useful when records need a stable external key separate from internal record IDs.
Color¶
A color value (hex or named color). Pages can render swatches and use the value in styling.
Timezone¶
An IANA timezone string such as America/New_York. Workflows use this to format dates and times for the right user.
URL¶
A web address. Use this instead of Text when the value should be entered with a scheme selector and validated as a URL. Stored values display as plain text, not as a clickable link.
Numeric¶
Use numeric fields when the value needs math, sorting, filtering, totals, or currency-aware formatting.
| Type | Best for | Stored value | Supported flags |
|---|---|---|---|
| Number | Counts, scores, quantities, percentages, and measurements. | A single numeric value. | Unique |
| Money | Prices, invoice totals, balances, adjustments, payments, and refunds. | Amount plus currency. | — |
Number¶
Use Number when the value is a count, measurement, rank, score, or any other number that is not currency.
| Setting | Why it matters |
|---|---|
| Integer | Restrict the value to whole numbers. |
| Minimum | Reject values below the threshold. |
| Maximum | Reject values above the threshold. |
Money¶
Use Money when the value represents a price, total, balance, adjustment, payment, refund, or amount owed.
Money fields store both the amount and the currency together so totals stay consistent across records. They work alongside the Payable, Itemizable, Payable Adjustment, Payment, and Refund Capabilities for invoice-style data, and with Stripe-backed payment workflows.
Boolean¶
A true or false value. Useful for flags like Active, Approved, Archived, or Marketing Opt-In.
Date and time¶
Date¶
A calendar date with no time portion. Use this for due dates, birthdays, and similar values where the time of day does not matter.
Time¶
A time of day with no date portion. Use this for daily schedules, opening hours, and time-of-day preferences.
Datetime¶
A specific point in time with both date and time. Use this for timestamps, appointments, and any value that needs to be ordered down to the minute or second.
Recurrence¶
A repeating schedule rule used inside an Event Schedule. Diagonal's recurrence editor supports daily, weekly, monthly, and yearly intervals, optional weekly days, and no end or a specific end date. A series can also end After N times (1 to 999). A cancelled occurrence still counts, and the end date moves when the pattern changes. The editor shows a summary such as "Weekly on Tuesday, 10 times", and "Changes on Dec 1" when a change from a later date is pending. An end date must be on or after the event start date. A series that ends before it starts is rejected. A change to an existing series is rejected when its new end date or After N times count puts the series end before today. A This and future occurrences change is also rejected when the new end comes before the occurrence being edited. After N times counts from the first date of the series, not from the edited occurrence. The record form does not offer "This occurrence" when Repeat changed.
Does not repeat stops the series. With "This and future occurrences", the edited date stays as a single event and the dates after it are removed. With "All occurrences", the edited date stays and every other date from today is removed. A past edited date stays in the series, and the stop starts today. A removed date that another record refers to, that the editor cannot update, or that a workspace hook protects stays, and the save response lists it. Setting the repeat again from an earlier date brings the removed dates back, and the single event stays beside the new date on its day. Setting the repeat on the single event itself starts a new series from that date. The removed dates do not come back, and each later date that stayed gets a second event on its day.
Event Schedule¶
A composite calendar value with required start, end, and all-day values, plus optional recurrence and exception data. The end must not be earlier than the start. An equal end is allowed. Eventable Resources require one Event Schedule field; use the capability settings for the calendar label, location, link, and description.
Regular Hours¶
The usual weekly hours of a Schedulable record, such as a tutor, a room, or a location. Map it with the Schedulable Regular hours field setting. The value is read in the record's own zone: its timezone field, or the workspace zone.
{
"periods": [
{ "from": null, "rules": [{ "days": ["monday", "wednesday"], "start": "15:00", "end": "20:00" }] },
{ "from": "2026-11-16", "rules": [{ "days": ["tuesday"], "start": "09:00", "end": "12:00" }] }
]
}
- Each period applies from its
fromdate until the next period, so a change from a date never rewrites earlier dates. One period can have a nullfrom, meaning it has always applied. A date before every dated period has no hours unless there is an undated period. - A rule opens
starttoendon each of itsdays,mondaytosunday. Rules can overlap. An end before the start runs past midnight, so20:00to00:00ends at midnight, and the same start and end is the whole day. - A value has at most 52 periods and 50 rules a period, and two periods cannot start on the same date. Each part reports its own error, such as
hours.periods.0.rules.1.start. - A period with no rules is closed on every day. An empty value means that the record has no hours of its own, so it takes the hours of the records in its Hours within relation. The admin editor edits a weekly grid by day, saves days with equal hours as one rule, and schedules changes from a date. Turning off every day keeps a closed week, and Clear hours removes the value.
Exports show the value as text, such as "Mon 15:00–20:00, Wed 15:00–20:00; from 2026-11-16: Tue 09:00–12:00". Regular Hours cannot be filtered on.
Rich content¶
Content¶
A rich text document.
Content fields store structured rich text rather than plain HTML, so you can keep the formatting clean and choose which features the editor exposes.
| Setting | Why it matters |
|---|---|
| Multi-line | Allow content to span multiple paragraphs and block-level nodes. |
| Extensions | Toggle inline formatting like bold, italic, strike, and underline. |
| Allowed nodes | Restrict block-level node types when multi-line is enabled. |
Markdown¶
Markdown source for content that should retain Markdown syntax. Use Content when builders need the structured rich-text editor instead.
To show an image at a set width, write the width in pixels right after the image: {width=430}. A linked image takes it inside the link: [{width=430}](https://example.com). The width is a whole number from 1 to 2000, and the height follows the image's proportions. The editor and the record page show the image at that width, and the editor keeps the width when you save. A width is the only attribute a Markdown field accepts. Any other attribute, such as {.class} or {height=200}, a width out of range, or an attribute on anything but an image fails validation. A field whose allowed formatting excludes images also refuses an image width.
Liquid¶
Liquid template source. Use this for builder-authored templates that the consuming workflow or email surface renders with an explicit Liquid context.
Files¶
File ID¶
An uploaded File reference such as an image, document, or PDF. The stored value resolves through Diagonal's File API rather than exposing an object-store path.
| Setting | Why it matters |
|---|---|
| Accepted file types | Limit uploads to specific MIME types. |
| Visibility | Choose Private (default) or Public. Public Files are accessible without authentication. Private Record Files require access to the Record and Field through Policies. |
Diagonal's upload UI and synchronous API limit Files to 50 MB. The browser's direct-to-storage path applies that limit before upload; the temporary upload URL itself doesn't validate the uploaded byte size. See Files and the Media Library for access rules and reusable assets.
Structured data¶
Dictionary¶
A keyed object made up of nested fields.
Use a Dictionary when a value has a fixed inner shape, such as an address with street, city, and postal code, or a settings object with named entries. The inner shape is defined by a nested schema.
List¶
An ordered collection of items.
Use a List when a record can have many of the same kind of value, such as tags, line items, or steps. The shape of each item is defined by a nested schema.
Select¶
A single value chosen from configured options. Use Select for a controlled status or category whose allowed values are part of the Field definition.
Location¶
A structured location value for addresses and geographic details that should stay together rather than being stored as unrelated Text Fields.
Event Schedule¶
A structured event-schedule value used by scheduling behavior. Use Recurrence for the repeating rule itself and Event Schedule when the consuming feature needs the combined schedule shape.
Dictionary vs List vs Relation
Use a Dictionary or List when the data lives inside the parent record. Use a Relation when the data should live in its own Resource and be queried, secured, or reused on its own.
Relations¶
Relation¶
A link from one Resource to another.
Relations are how your app expresses that an Order belongs to a Customer, a Customer has many Orders, an Employee has one Profile, or Students enroll in many Courses. See the Resources guide for the four relation kinds and how to model them.
| Setting | Why it matters |
|---|---|
| Type | Belongs to, Has one, Has many, or Belongs to many. |
| Target resource | The other Resource this field points to. |
| Foreign key | The field on the related Resource that stores the link. |
| Filters | Optional filters that constrain which records the relation can reference. |
| Nullable | Allow the relation to be left empty (Belongs to). |
| Inverse | Optionally expose this relation from the other side. |
Cross-field flags¶
Two flags appear next to most fields. Each flag is supported by a specific subset of types:
| Flag | Supported types |
|---|---|
| Searchable | Text, Email, Phone |
| Unique | Text, Number, Email, Phone, Date, Uuid |
Searchable should be turned on intentionally — every field that opts in adds work to query and indexing paths. Unique is enforced at the database level and rejects records that would create a duplicate value.
Computed values (setters)¶
A field can have a setter. A setter is a resolver that calculates the field value each time a record is saved. The platform stores the result and then validates it.
- Turn on Only when empty to run the setter only when the field is empty. A value that the user entered stays as it is. This is the usual way to fill a field only when it is blank.
- Without Only when empty, the setter runs when a record is created and each time it is updated, also when the update does not change the field. Make the setter give the same result when it runs again.
- The setter can read the value that the user entered for the field, the other fields of the record (including the record id), the field, and the resource.
- A setter can only calculate a value. A setter that creates, changes, or sends data is rejected.
- A required field with a setter can be left empty on create. The setter fills it.
- Setters do not run on virtual fields. Do not add a setter to a Password field, because it replaces the password hashing.
Example: a unique Slug field has Only when empty turned on. It keeps a slug that the user typed. If the user leaves it empty, the setter makes the slug from the title and the record id, for example spring-sale-0199c0de.
On a recurring Eventable resource, each new occurrence calculates its own value for a unique field that has a setter. This also applies when Only when empty is on. A recurring change that would copy one unique value to every occurrence is rejected when that field has no setter.