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 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:

swell create content

→ See the CLI reference for more details and options.

Here's an example of a new content model:

content/things.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.

See the Content model reference for more information.

Content model collections are private by default, however they can be made to support accessing data from the frontend API 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 for details.

Here’s an example model with a public field:

{
  "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 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 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.

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.

Actions are buttons displayed on list and record views, either in the page header or in the Actions menu in the Swell dashboard. The most basic action can be configured to navigate to another page, either in the dashboard or externally. More advanced actions can point to a page of the app's own frontend, displayed within the dashboard, to process data and apply changes to the current view.

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: The type of action, one of link, modal, new, save, clone, delete, or import_export.
  • conditions: Criteria evaluated against the current record. The action is only displayed while its conditions match.

List view actions support id (required), label, link, external, and type, one of default, primary, danger, or sub. Conditions are not evaluated on list view actions.

When a view does not define actions, list views include a New action and record views include Save and Delete actions by default. Defining actions replaces these defaults, so include the built-in ids alongside custom actions to keep them. 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:

{
  "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:

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

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

content/things.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
{
  "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.