# The content model

Source: https://developers.swell.is/backend-api/content-models/the-content-model

## Fields

- `id` (string, auto): Unique identifier for the model.
- `label` (string): Plural name of the content model collection.
- `name` (string, required, auto): System name of the model. Defaults to `[collection].[root]`.
- `collection` (string, required): Specifies the model collection to create or enhance. The collection may be entirely new to the store or to an app that defines it, or may refer to a standard model such as `products`.

  You may specify a namespace for the model which becomes part of its API endpoint, for example `collection: content/testimonials` would result in an API endpoint such as `/content/testimonials`. Also note, any content model defined in the `content` namespace is automatically made public, unless `public: false` is set.
- `fields` (array of field, required): Content fields and their properties applied for each record of a collection.
  - `id` (string, required): String ID of the content field representing the name of a model field. This must be unique when combined with the `root` property.

    For example: `my_field`
  - `label` (string): Optional label of the field used in the Swell dashboard.
  - `description` (string): A brief description of the field.
  - `type` (string, required): Type of the field. Content fields present a configurable UI in the Swell dashboard, and also apply relevant data types to their respective data model, as defined by `collection`.

    Basic types have a number of `ui` options that affect how the field is displayed in the dashboard.

    - `short_text`
       - ui: `default` (text), `slug`, `email`, `phone`, `url`
       - data type: `string`
    - `long_text`
       - ui: `default` (textarea), `rich_text`, `basic_html`, `rich_html`, `markdown`, `liquid`
       - data type: `string`
    - `boolean`
       - ui: `default` (checkbox), `toggle`
       - data type: `bool`
    - `select`
       - ui: `default` (dropdown), `radio`, `checkboxes`
       - data type: `array<string>`
    - `number`
       - ui: `default` (integer), `float`, `currency`, `slider`
       - data type: `int`, `float`, `currency`
    - `date`
       - ui: `default` (date), `time`, `datetime`
       - data type: `date`
    - `asset`
       - ui: `default` (flexible), `image`, `video`, `document`
       - data type: `file`
    - `tags`
       - Default `ui` renders a tag input
       - data type: `array<string>`
    - `color`
       - Default `ui` renders a color picker
       - data type: `string`
    - `icon`
       - Default `ui` renders an icon picker
       - data type: `string`
    - `lookup`
       - Default `ui` render a lookup component
       - data type: `objectid`
    - `collection`
       - An array of nested objects
       - data type: `array<object>`
    - `field_group`
       - Wrapper that renders a group fields **vertically**
    - `field_row`
       - Wrapper that renders a group fields **horizontally**
    - `action`
       - Button that runs an app function or workflow in the Swell dashboard, and stores no data. Set `function` to the function's name. See [Actions](https://developers.swell.is/apps/actions).

    The following are UI-specific aliases for configurations intended to help simplify many CMS use cases. When used as a `type`, their respective properties are automatically applied to the field and can each be overridden.

    - `text`
       - type: `short_text`
    - `textarea`
       - type: `long_text`
    - `rich_text`
       - type: `long_text`
       - ui: `rich_text`
    - `checkbox`
       - type: `boolean`
    - `checkboxes`
       - type: `select`
       - ui: `checkboxes`
       - multi: `true`
    - `toggle`
       - type: `boolean`
       - ui: `toggle`
    - `radio`
       - type: `select`
       - ui: `radio`
    - `dropdown`
       - type: `select`
    - `integer`
       - type: `number`
       - digits: `0`
    - `float`
       - type: `number`
       - digits: `2`
    - `currency`
       - type: `number`
       - ui: `currency`
    - `percent`
       - type: `number`
       - unit: `%`
    - `slider`
       - type: `number`
       - ui: `slider`
       - increment: `1`
    - `time`
       - type: `date`
       - ui: `time`
    - `datetime`
       - type: `date`
       - ui: `datetime`
    - `phone`
       - type: `short_text`
       - ui: `phone`
    - `email`
       - type: `short_text`
       - ui: `email`
    - `url`
       - type: `short_text`
       - ui: `url`
    - `slug`
       - type: `short_text`
       - ui: `slug`
    - `html`
       - type: `long_text`
       - ui: `basic_html`
    - `basic_html`
       - type: `long_text`
       - ui: `basic_html`
    - `rich_html`
       - type: `long_text`
       - ui: `rich_html`
    - `markdown`
       - type: `long_text`
       - ui: `markdown`
    - `liquid`
       - type: `long_text`
       - ui: `liquid`
    - `image`
       - type: `asset`
       - asset_types: `[image]`
    - `document`
       - type: `asset`
       - asset_types: `[document]`
    - `video`
       - type: `asset`
       - asset_types: `[video]`
    - `child_collection`
       - type: `collection`
       - child: `true`
    - `product_lookup`
       - type: `lookup`
       - collection: `products`
    - `variant_lookup`
       - type: `lookup`
       - collection: `products:variants`
    - `category_lookup`
       - type: `lookup`
       - collection: `categories`
    - `customer_lookup`
       - type: `lookup`
       - collection: `accounts`
  - `ui` (string): Enumerated UI-types, when combined with `type`, allows you to render various different components in the Swell dashboard for the same underlying data field. Each `ui` only works relative to a specific `type. See the` **`field.type`** `documentation for details.`

    *Note:* *`ui`* *values are different than* *`type`* *aliases as documented, however they may share the same name.*
  - `fields` (array of field): Required for `field_group`, `field_row`, and `collection` only, defines the nested fields of the group. The fields of a group are of the same schema as the top-level fields property.
  - `value_type` (enum): Optionally specify the data type used to store this value in a model collection. Content field `type` is cast to `value_type` when a record is created or updated. Defaults to the appropriate data type for a given content field type. Possible values: `array`, `bool`, `collection`, `currency`, `date`, `float`, `link`, `string`, `object`, `objectid`.
  - `item_types` (array of item_type): For `collection` only, define groups of nested fields that are applied to collection records. In the respective data model, these are defined as `object_types` according to the nested content field schema.
    - `id` (string, required): ID of the item type. This becomes the key of a related model collection's `object_types`.
    - `name` (string): Optional name of the item type used in the Swell dashboard.
    - `fields` (array of field): Content fields displayed for the item type, using the same schema as the top-level fields property.
  - `conditions` (object): A query object used to match record values. When matched, the field is visible, otherwise it is hidden. Field conditions support the equivalent format and operators of [query filtering](https://developers.swell.is/backend-api/querying/filtering#filtering).
  - `required` (boolean): Indicates the field must be defined with a non-empty value when the record is created or updated.
  - `default` (mixed): Global default value of the field, applied to all records at runtime when retrieved by the API. The Swell dashboard supports overriding this value per-record, and also the ability to reset the value to the global default.

    If `fallback` is set to `false`, then the default is stored on the record locally when created from the Swell dashboard.
  - `public` (boolean): Indicates that a field value is made accessible by a public API call, assuming the parent content model does not have `public: true`.
  - `fallback` (boolean): Indicates the `default` value should fallback to the global default. Defaults to `true`.
  - `enum` (array of value): Enumerated set of values accepted by the system.
  - `format` (string): Automatically format the value of a string field. This may be an alternative to a more complex formula for simple use cases.

    **One of:**

    - `uppercase`: value => VALUE
    - `lowercase`: VALUE => value
    - `underscore`: TextValue => text_value
    - `slug`: TextValue => text-value
    - `slugid`: TextValue.Example => text-value.example
    - `currency-code`: usd => USD
    - `url`: example.com => https://example.com
    - `email`: user name@example.com => user+name@example.com
    - `semver`: 1 => 1.0.0
    - `password`: example => bcrypt(example)
       - Password-formatted fields are automatically hashed with the [bcrypt](https://en.wikipedia.org/wiki/Bcrypt) algorithm.
  - `formula` (string): An expression used to calculate the value of the field when a record is created or updated. See [Formula documentation](https://developers.swell.is/backend-api/formula) for more details.
  - `readonly` (boolean): Indicates the field cannot be changed after initially being defined. Note: a `formula` field may still change the value dynamically.
  - `unique` (mixed): If set to `true`, indicates the value must be unique across the entire collection. If set as an array of adjacent fields, indicates the combination of values must be unique across the entire collection.

    For example, the following would specify a field must be unique when combined with `account_id`:

    `"unique": ["account_id"]`
  - `localized` (boolean): Indicates that a string or currency value can be localized by locale and currency codes in the Swell dashboard.
  - `hint` (string): Text hint typically displayed below the field input in the Swell dashboard.
  - `root` (mixed): The object path data fields will be applied to in the respective model collection. For example, on the `accounts` collection, to root a field to the shipping object, set `root: shipping`.

    If `undefined`, the field will be rooted to the model's `content` object, which is accessible by a public API call.

    If true, the field will be rooted at the top-level of the model schema.
  - `admin_span` (int): Number of columns for the field to span, between `1` and `4`. The Swell dashboard interface supports a grid of up to 4 columns on a page. Defaults to `4`.
  - `admin_zone` (string): Specifies the area of the Swell admin dashboard for the field to appear. Most standard collections have pre-defined zones that are distributed throughout the dashboard UI. Some zones will change the root of the content fields, for example scoping fields to a variant record instead of the parent product.

    **If the** **`admin_zone`** **is empty, the field is hidden from the UI.**

    The following are zones displayed by each standard collection. Note: app-defined or custom collections only support the `content` zone.

    `products`:

    - `details`: The main details section.
    - `pricing`: The pricing section.
    - `options`: The options section.
    - `option-edit`: The interface to edit an option.
       - root: `options`
    - `option-value-edit`: The interface to edit an option value.
       - root: `options.values`
    - `variant-edit:` The interface to edit a variant.
       - root: `variants`
    - `related`: The related products section.
    - `attributes`: The attributes tab.
    - `inventory`: The inventory tab.
    - `shipping`: The shipping tab.
    - `content`: The content section at the bottom of the page.

    categories:

    - `details`: The main details section.
    - `content`: The content section at the bottom of the page.

    `accounts`:

    - `details`: The main details section.
    - `contact`: The interface used to edit contact information.
    - `billing`: The interface used to edit billing information.
       - root: `billing`
    - `shipping`: The interface used to edit shipping information.
       - root: `shipping`

    `orders`:

    - `details`: The main details section.
    - `content`: The content section at the bottom of the page.

    `subscriptions`:

    - `details`: The main details section.
    - `content`: The content section at the bottom of the page.

    `invoices`:

    - `details`: The main details section.
    - `content`: The content section at the bottom of the page.

    `carts`:

    - `details`: The main details section.
    - `content`: The content section at the bottom of the page.

    `payments`:

    - `charge`: The interface to charge a payment method.
    - `refund`: The interface to refund a payment.
       - root: `refunds`

    `shipments`:

    - `order`: The interface for an order fulfillment.

    `returns`:

    - `order`: The interface for an order return.

    `attributes`:

    - `content`: The content section at the bottom of the page.

    `giftcards`:

    - `content`: The content section at the bottom of the page.

    `coupons`:

    - `content`: The content section at the bottom of the page.

    `promotions`:

    - `content`: The content section at the bottom of the page.

    `purchaselinks`:

    - `content`: The content section at the bottom of the page.

    `content/pages`:

    - `content`: The content section at the bottom of the page.

    `content/blogs`:

    - `content`: The content section at the bottom of the page.
  - `multi` (boolean): For `select` only, indicates the value should support multiple selections.
  - `model` (string): For `lookup` only, specifies the model to query when looking up records in the Swell dashboard.
  - `key` (string): For `lookup` only, optionally specifies the foreign key to reference the primary or secondary key of a linked collection. The key field is automatically created on its respective data model using this name, or if not defined, it will create a field in the format of `[lookup-field-name]_id`.
  - `key_field` (string): For `lookup` only, optionally specifies the name of a secondary field that the `key` value refers to. For example, if `model=products` and you preferred the lookup key to store the `slug` value of a product (which is used as its secondary key), then you would set `key_field=slug`.
  - `limit` (int): For `lookup` only, limits the number of results to display in a lookup query UI.
  - `min` (float): Requires a minimum value of a `number` field.
  - `max` (float): Requires a maximum value of a `number` field.
  - `digits` (int): For `number` only, determines the number of decimal digits rounded to.
  - `item_label` (string): For `collection` only, refers to the collection field that should be used as a label in the collection list.
  - `icon` (string): For `collection` only, specifies an icon to be displayed next to each row of a collection list.
  - `asset_types` (array of asset_type): For `asset` only, indicates the file types acceptable for upload. Defaults to allow any file type.
- `public` (boolean): Indicates that collection records are accessible by a public API call.
- `views` (array of view): Content views allowing you to configure different layouts for `list` and `record` pages. List views allow you to add fields and filters to collection lists, while record views allows you to add fields to record pages.
  - `id` (string, required): ID of the view. List views must have either `id=list` or `type=list`, while other IDs are always evaluated as `record` type views.

    **Standard view IDs:**

    - `list`: Configures columns (fields) in a collection list.
    - `record`: Configures fields on a record page.
    - `new`: Configures fields on a record page only when creating a new record.
    - `edit`: Configures fields on a record page only when editing an existing record.
  - `type` (string): Type of the view, either `list` or `record`. Defaults to list if `id=list`, or `record` otherwise.
  - `label` (string): Optional label of the view to display in the Swell dashboard.
  - `fields` (array of field): Fields to be displayed in the view. The only required field property is `id`, however you may override any field property to change its behavior in the view layout specifically.

    View fields are used in both `list` and `record` layouts, while `list` views may ignore certain properties that are only relevant to `record` views.
  - `tabs` (array of tab): For `list` only, defines query tabs that filter results in a collection.
    - `id` (string, required): Custom ID used in the URL when a user navigates to this tab. Typically a simplified version of the `label`.
    - `label` (string, required): Label displayed as the tab text in the collection list UI.
    - `query` (object): Query used to filter collection results when the tab is active.
      - `where` (object): A query object used to filter records in a collection list. Support the equivalent format and operators of [query filtering](https://developers.swell.is/backend-api/querying/filtering#filtering).
      - `limit` (int): Limits the number of results displayed in a page by default.
      - `sort` (string): Specifies the default sort directive of the collection query. For example: `sort: name asc`.
  - `actions` (array of action): Buttons in the view's header. Each item is a built-in action id (`new`, `save`, or `delete`) or an action object that opens a link or runs an app function. See [Actions](https://developers.swell.is/apps/actions).
    - `id` (string, required): ID of the action.
    - `label` (string): Label of the action displayed in the Swell dashboard.
    - `external` (boolean): Indicates the action will make an API call to an external URL.
    - `link` (string): Link to an internal or external URL when the action is performed.
    - `function` (string): Name of an app function or workflow to run when the action is clicked. The function must declare `action: true`. Cannot be combined with `link`.
    - `target` (string): Where a link opens, usually `blank` or `self`.
    - `hint` (string): Tooltip shown after hovering over the action for 2 seconds.
    - `loading_label` (string): Text shown while the function runs. Defaults to the label followed by an ellipsis.
    - `modal` (object): Dialog shown before the function runs, with an optional `title`, `description`, `submit_label`, and `fields`. Field values are sent to the function.
    - `conditions` (object): Query that must match the current record for the action to appear.
    - `hidden` (boolean): Indicates the action is hidden. A hidden function action cannot be run.
    - `type` (string): Button style: `default`, `primary`, `secondary`, or `danger`.
  - `extra_actions` (array of action): Items in the view's Actions menu, in the same format as `actions`.
  - `bulk_actions` (array of action): For list views only. Buttons in the bulk bar, shown when records are selected. Each must run an app function, which receives the selected records. Declaring any makes the list selectable.
- `defaults` (object, auto): Aggregate global `default` values derived from field defaults. These values are automatically applied to API responses when using the `$content: true` operator.
- `source_type` (enum, required, auto): Indicates the source of the content model, `app` or `custom`. The value is automatically set to `custom` when created from the Swell dashboard. Possible values: `app`, `custom`. Default: `"custom"`.
- `app_id` (objectId): ID of a Swell App that defined this model, if applicable.
- `date_created` (date, auto): Date the model was created.
- `date_updated` (date, auto): Date the model was last updated.

## Example response

```json
{
  "collection": "reviews",
  "fields": [
    {
      "id": "account",
      "label": "Reviewer",
      "type": "customer_lookup",
      "description": "The customer who wrote the review",
      "required": true
    },
    {
      "id": "product",
      "label": "Product",
      "type": "product_lookup",
      "description": "The product being reviewed",
      "required": true
    },
    {
      "id": "title",
      "label": "Review title",
      "type": "text",
      "description": "The title of the review",
      "required": true
    },
    {
      "id": "body",
      "label": "Review body",
      "type": "long_text",
      "description": "The body of the review",
      "required": true
    },
    {
      "id": "rating",
      "label": "Rating",
      "type": "slider",
      "unit": "stars",
      "min": 1,
      "max": 5,
      "description": "Rating (1-5) of the reviewed product",
      "admin_span": 1,
      "required": true
    },
    {
      "id": "images",
      "label": "Images",
      "type": "image",
      "description": "Images associated with the review",
      "multi": true,
      "conditions": {
        "$settings.images.enabled": true
      }
    },
    {
      "id": "status",
      "label": "Status",
      "type": "select",
      "description": "Admin status of the review",
      "default": "submitted",
      "admin_span": 2,
      "options": [
        {
          "label": "Submitted",
          "value": "submitted"
        },
        {
          "label": "Approved",
          "value": "approved"
        },
        {
          "label": "Rejected",
          "value": "rejected"
        }
      ]
    },
    {
      "id": "rejected_reason",
      "label": "Rejected reason",
      "type": "long_text",
      "description": "Reason for rejecting the review, may be visible to the customer",
      "conditions": {
        "status": "rejected"
      }
    },
    {
      "id": "reward_amount",
      "label": "Reward amount",
      "type": "currency",
      "description": "Amount to reward the customer for writing the review",
      "admin_span": 1,
      "conditions": {
        "$settings.rewards.enabled": true,
        "status": "approved",
        "reward_disabled": { "$ne": true },
        "rewarded": { "$ne": true }
      }
    },
    {
      "id": "reward_disabled",
      "label": "Disable reward",
      "type": "toggle",
      "conditions": {
        "$settings.rewards.enabled": true,
        "status": "approved",
        "rewarded": { "$ne": true }
      }
    },
    {
      "id": "verified_buyer",
      "label": "Verified buyer",
      "type": "toggle",
      "description": "Indicates the reviewer has purchased the product",
      "conditions": {
        "$settings.verified.enabled": true
      }
    },
    {
      "id": "featured",
      "label": "Featured",
      "type": "toggle",
      "description": "Indicates the review may be featured in your storefront",
      "conditions": {
        "$settings.featured.enabled": true
      }
    },
    {
      "type": "field_row",
      "fields": [
        {
          "id": "like_count",
          "label": "Like count",
          "type": "number",
          "description": "Indicates the number of likes the review has received",
          "readonly": true
        },
        {
          "id": "dislike_count",
          "label": "Dislike count",
          "type": "number",
          "description": "Indicates the number of dislikes the review has received",
          "readonly": true
        }
      ]
    },
    {
      "id": "comments",
      "label": "Comments",
      "type": "child_collection",
      "fields": [
        {
          "id": "account",
          "label": "Customer",
          "type": "customer_lookup",
          "description": "The customer who wrote the comment",
          "required": true
        },
        {
          "id": "body",
          "label": "Comment body",
          "type": "long_text",
          "description": "The body of the comment",
          "required": true
        },
        {
          "id": "status",
          "label": "Status",
          "type": "select",
          "description": "Admin status of the comment",
          "default": "submitted",
          "options": [
            {
              "label": "Submitted",
              "value": "submitted"
            },
            {
              "label": "Approved",
              "value": "approved"
            },
            {
              "label": "Rejected",
              "value": "rejected"
            }
          ]
        },
        {
          "id": "rejected_reason",
          "label": "Rejected reason",
          "type": "long_text",
          "description": "Reason for rejecting the comment, may be visible to the customer",
          "conditions": {
            "status": "rejected"
          }
        },
        {
          "id": "verified_buyer",
          "label": "Verified buyer",
          "type": "toggle",
          "description": "Indicates the user has purchased the product",
          "conditions": {
            "$settings.verified.enabled": true
          }
        },
        {
          "type": "field_row",
          "fields": [
            {
              "id": "like_count",
              "label": "Like count",
              "type": "number",
              "description": "Indicates the number of likes the comment has received",
              "readonly": true
            },
            {
              "id": "dislike_count",
              "label": "Dislike count",
              "type": "number",
              "description": "Indicates the number of dislikes the comment has received",
              "readonly": true
            }
          ]
        }
      ]
    }
  ],
  "views": [
    {
      "id": "list",
      "nav": {
        "parent": "products",
        "label": "Honest Reviews"
      },
      "tabs": [
        {
          "id": "approved",
          "label": "Approved",
          "query": {
            "status": "approved"
          }
        },
        {
          "id": "rejected",
          "label": "Rejected",
          "query": {
            "status": "rejected"
          }
        },
        {
          "id": "verified",
          "label": "Verified buyers",
          "query": {
            "verified_buyer": true
          }
        }
      ],
      "fields": [
        {
          "id": "title"
        },
        {
          "id": "product"
        },
        {
          "id": "body",
          "truncated": 100
        },
        {
          "id": "rating",
          "template": "{{ rating }} {{ rating | default: 1 | pluralize: 'star','stars' }}"
        },
        {
          "id": "account"
        },
        {
          "id": "status"
        },
        {
          "id": "comments"
        },
        {
          "id": "date_created",
          "label": "Submitted"
        },
        {
          "id": "reward_amount",
          "conditions": {
            "$settings.rewards.enabled": true
          }
        },
        {
          "id": "verified_buyer",
          "conditions": {
            "$settings.verified.enabled": true
          }
        },
        {
          "id": "featured",
          "conditions": {
            "$settings.featured.enabled": true
          }
        }
      ]
    },
    {
      "id": "new",
      "fields": [
        {
          "type": "field_row",
          "fields": [
            {
              "id": "account"
            },
            {
              "id": "product"
            }
          ]
        },
        {
          "id": "title"
        },
        {
          "id": "body"
        },
        {
          "id": "rating"
        },
        {
          "id": "images"
        },
        {
          "id": "status"
        },
        {
          "id": "rejected_reason"
        },
        {
          "id": "reward_amount"
        },
        {
          "id": "reward_disabled"
        },
        {
          "id": "verified_buyer"
        },
        {
          "id": "featured"
        },
        {
          "id": "comments"
        }
      ]
    },
    {
      "id": "edit",
      "title": "{{ title }}",
      "subtitle": "By {{ account.name }}",
      "fields": [
        {
          "type": "field_row",
          "fields": [
            {
              "id": "account"
            },
            {
              "id": "product"
            }
          ]
        },
        {
          "id": "title"
        },
        {
          "id": "body"
        },
        {
          "id": "rating"
        },
        {
          "id": "images"
        },
        {
          "id": "status"
        },
        {
          "id": "rejected_reason"
        },
        {
          "id": "reward_amount"
        },
        {
          "id": "rewarded_amount",
          "readonly": true,
          "type": "currency",
          "default": "{{ reward_amount }}",
          "conditions": {
            "rewarded": true,
            "reward_amount": { "$gt": 0 }
          }
        },
        {
          "id": "reward_disabled"
        },
        {
          "id": "verified_buyer"
        },
        {
          "id": "featured"
        },
        {
          "id": "comments"
        },
        {
          "type": "field_row",
          "conditions": {
            "$settings.reactions.enabled": true
          },
          "fields": [
            {
              "id": "like_count",
              "admin_span": 1
            },
            {
              "id": "dislike_count",
              "admin_span": 1
            }
          ]
        }
      ]
    }
  ]
}
```
