# Content

Source: https://developers.swell.is/apps/content

Content models are a layer above data models, with the primary purpose of defining the content management experience presented in a store’s dashboard.

This two-tiered approach makes it easier to separate concerns between the database schema, API functionality, and administrative workflows. See our guide on [content models vs data models](https://developers.swell.is/guides/model-customization) for more details.

You can create a new content model by adding a configuration to the app's `content/` folder, or by using the following CLI command:

```sh
swell create content
```

→ See the [CLI reference](https://developers.swell.is/apps/cli) for more details and options.

#### Example

Here's an example of a new content model:

**content/things.json**

`content/things.json`

```json
{
	"collection": "things",
	"fields": [
		{
			"id": "name",
			"type": "text"
			"required": true
		},
		{
			"id": "description",
			"type": "long_text"
			"hint": "Describe this thing in 2-3 sentences"
		}
	]
}
```

Notice the difference between content and data model configurations. Content models prefer UI-oriented field types, which for example can specify short vs long text, and field ordering to display in the admin dashboard, while data models are purely schema-oriented to structure the database and related APIs.

In the above example, the `things` collection is not standard, therefore a new data model and collection will be established by the app. If it did exist, then the platform would automatically enhance the underlying data model associated with that collection.

> **Tip:** See the [Content model reference](https://developers.swell.is/backend-api/content-models/the-content-model) for more information.

## Public permissions

Content model collections are private by default, however they can be made to support accessing data from the [frontend API](https://developers.swell.is/frontend-api/introduction) in three ways:

- Specify `public: true` at the top-level.
- Specify the collection in the content namespace, for example: `collection: content/testimonials`.
- Specify `public: true` on individual content fields, in which case only those fields which are made public will be available via the frontend API.

These methods will make some or all collection data readable. In order to make data writable, add `public_permissions` to the respective data model. See the [Data model reference](https://developers.swell.is/apps/models) for details.

#### Example

Here’s an example model with a public field:

`models/things.json`

```json
{
	"collection": "vendors",
	"label": "Vendors",
	"fields": {
		"name": {
			"type": "string",
			"required": true,
			"public": true
		},
		"active": {
			"type": "bool"
		},
		"description": {
			"type": "string"
		}
	},
	"public_permissions": {
		"query": {
			"active": true
		},
		"expands": {
			"products": {
				"url": "/products",
				"params": {
					"vendor_id": "id"
				},
				"data": {
					"active": true
				}
			}
		}
	}
}
```

With at least 1 public field declared, all records can be accessed by the frontend API, with only the public fields being returned in a response. In addition, you can limit the range of results to only include active records using `public_permissions`, and specify how expand parameters should be treated for the collection in a public scope.

## Views

Views are an aspect of content models used to provide merchants with different ways of visualizing and editing data, as well as defining app-specific actions for standard and custom models.

Views are configurations that represent fully functional, native pages in the Swell dashboard. There are two primary types of views: List (`list`) and Record (`edit`, and `new`). List views display collections of items, while Record views focus on displaying the details of a single item. Apps can address various use cases to help merchants manage data within the dashboard by adding Tabs and Fields to both standard and app-specific collections.

### List and record views

List views provide an overview of content, displaying multiple items in a structured format, often with filtering and sorting capabilities. Record views, on the other hand, focus on a single content item, allowing for in-depth management and modification of its properties. Both view types can be customized to fit specific use cases and requirements.

### View tabs and fields

Both List and Record views can organize fields into tabs that can be sorted and hidden by a merchant. They can be applied to any standard or app-defined view, giving merchants full control over their dashboard workflows. View fields can refer to standard or app-defined data, and apply UI validation, help descriptions, and more.

Fields can also be displayed or locked dynamically based on record data: a field's `conditions` determine when it is shown, and `readonly` accepts either a boolean or a conditions object, making the field read-only when the criteria match the current record.

A field with `type: "action"` is a button that runs an app function, and stores no value. See [Actions](https://developers.swell.is/apps/actions).

### View actions

Actions are buttons displayed on list and record views, either in the page header or in the Actions menu in the Swell dashboard. An action can navigate to another page, either in the dashboard or externally, or to a page of the app's own frontend displayed within the dashboard. An action can also run an app function or workflow. A view's `actions` appear in its header, its `extra_actions` in its Actions menu, and a list view's `bulk_actions` in the bulk bar when records are selected. See [Actions](https://developers.swell.is/apps/actions) for actions that run functions.

Record view actions support the following properties:

- `id`: Identifier of the action. The built-in ids `new`, `save`, and `delete` apply standard behaviors: `save` submits the record form, `delete` deletes the record, and `new` opens the record creation page.
- `label`: Label displayed on the action button. Defaults to a formatted version of the id.
- `link`: URL the action navigates to. Supports `{field}` placeholders that are replaced with values from the current record, for example `frontend://reviews/{id}`.
- `external`: Indicates whether the link opens as an external URL instead of being routed within the dashboard.
- `submit`: Indicates whether the action submits the record form, saving any pending changes.
- `icon`: Icon identifier displayed on the action button.
- `type`: Button style of a header button: `default`, `primary`, `secondary`, or `danger`.
- `conditions`: Criteria evaluated against the current record. The action is only displayed while its conditions match.
- `function`: Name of an app function or workflow to run when the action is clicked. Cannot be combined with `link`.
- `modal`: Dialog shown before the function runs, to confirm the action or collect input.
- `hint`: Tooltip shown after hovering over the action for 2 seconds.
- `loading_label`: Text shown while the function runs.
- `hidden`: Hides the action.
- `target`: Where a link opens, usually `blank` or `self`.

List view actions support the same properties. In list views, `conditions` are evaluated against an empty record for link actions, and ignored for function actions.

When a view does not define actions, list views include a New action, and record views include a Save action in the header and a Delete action in the Actions menu. Defining `actions` or `extra_actions` replaces these defaults, unless every item runs an app function, in which case the items are added after the defaults. To keep a default alongside custom link actions, include its built-in id. Record view actions defined on standard collections such as products are also added to the Actions menu of the corresponding dashboard pages.

A record view action can also define `conditions` evaluated against the current record, so the action is only displayed when the criteria match. Conditions support the same query operators as view and field conditions, such as `$ne`, `$gt`, and `$in`, and can reference fields defined by other apps using `$app.<app_id>.<field>` keys. For example:

```json
{
  "actions": [
    {
      "id": "view-orders",
      "label": "View orders",
      "type": "link",
      "link": "/orders",
      "conditions": {
        "status": "active"
      }
    }
  ]
}
```

An action's `link` can also point to the app's own frontend using the `frontend://` scheme. The path after the scheme resolves to a route in your app frontend, which is displayed embedded within the Swell dashboard. For example:

```json
{
  "actions": [
    {
      "id": "view-report",
      "label": "View report",
      "type": "link",
      "link": "frontend://reports/sales"
    }
  ]
}
```

An action can also run an app function. Set `function` to the name of a function or workflow that declares `action: true`:

```json
{
  "actions": [
    {
      "id": "send_to_warehouse",
      "label": "Send to warehouse",
      "function": "send-product"
    }
  ]
}
```

→ See [Actions](https://developers.swell.is/apps/actions) for dialogs, bulk actions, action fields, and what the function receives.

## Examples

Here's an example of a basic view configuration for the things content model:

**content/things.json**

`content/things.json`

```json
{
  "collection": "things",
  "fields": [
    {
      "id": "name",
      "type": "text",
      "required": true
		},
    {
      "id": "description",
      "type": "long_text",
      "hint": "Describe this thing in 2-3 sentences"
    },
		{
			"id": "status",
      "type": "select",
			"options": [
				{ "value": "active", "label": "Active" },
				{ "value": "inactive", "label": "Inactive" },
			]
		}
  ],
  "views": [
		{
			"id": "list",
			"type": "list",
      "fields": [
        { "id": "name" },
        { "id": "description" }
      ],
      "filters": [
        {
					"id": "status",
					"type": "select",
					"label": "Status"
				}
      ]
		}
  ]
}
```

In this example, we've defined a `list` view for the `things` content model, specifying the columns to be displayed, the actions available, and a filter for the `status` field.

You can also modify existing views of a content model by referencing the specific view you want to modify. Here's an example of how to add a tab to the `list` view of the `products` content model:

**content/products.json**

```json
{
  "collection": "products",
  "views": [
		{
	    "list": {
	      "tabs": [
	        {
						"id": "my_app_tab",
						"label": "Product things",
						"query": {
							"$app.my_app.thing_id": { "$ne": null }
						},
						"fields": [
							{ "id": "name" },
							{ "id": "thing_id" }
						]
					}
	      ]
	    }
		}
  ]
}
```

In this example, we've added a new tab called “Product things” to the `list` view of the `products` content model. The tab also specifies which fields should be visible on the tab by default.

Views can be used in combination with Swell's webhooks and serverless functions to create a seamless, personalized experience for merchants. More information about webhooks and functions can be found in later sections of the documentation.
