This section will help you understand and begin the different elements involved in building a Swell App. Our goal is to make it easy and fun to extend the platform, and to help move commerce forward faster than ever.

Building an App

<aside> đź’ˇ This product is in development throughout 2024. To get early access, contact our partner team at [email protected].

</aside>

Getting started

For a more concrete example of what a full application build looks like, we’ve developed a sample app called Honest Reviews for you to explore. Tutorial: Building Honest Reviews.

Once you’re familiar with the structure of a Swell App, your first step is to decide what kind of app to develop. Keep in mind that an app can fulfill many capabilities at once, which allows you to package a cohesive set of functionality into a single package for merchants to use.

Installing the CLI

You’ll use the Swell CLI to develop and install apps, so you should be comfortable using command-line interfaces, Node.js tooling, and JSON structures. Make sure you have a Swell account which has been granted access to create Apps by the Swell partner team.

Note: During development, app configurations and functions are always synced to your Test environment. When you’re ready to push an app to a Live environment, you’ll routinely use the CLI to perform installation.

To begin, run the following command in a new folder:

swell create app

Next: Read more about the development workflow, or continue to learn about the structure of apps below.

Structure

An app is essentially a package of configurations and code for serverless functions. It might do something as simple as add a field to an existing model, or as complex as a multi-faceted storefront experience with many backend endpoints and dashboard views.

The following sections represent the building blocks of an app and their representation in the package.

Models

There are two types of model configurations representing both low-level database fields, and high-level content management interfaces. To learn more about these concepts, read the Models introduction and our general guide on Data model customization.

With an understanding of how models work, you can construct app configurations that automatically introduce new models as well as new fields to standard models when installed.

Data models

A data model configuration has the ability to modify a merchant store’s own data schema in a secure, observable, and isolated manner.

Since Swell data models are dynamically instantiated as REST endpoints, any models you define will essentially enhance a merchant’s own API in what feels like a first-class, native interface. See architecture if you’re interested in how it works.

You can create a new data model via the Backend API, or by using the following CLI command:

swell create model

Note: See the CLI reference for more details and options.

Here’s an example of a new data model:

models/things.json

{
	"collection": "things",
	"label": "Things",
	"fields": {
		"name": {
			"type": "string",
			"required": true
		},
		"description": {
			"type": "string"
		}
	}
}

A model configuration can either instantiate a new collection, such as above, or append to an existing collection such as products.

Here’s an example of appending fields to an existing collection:

models/products.json

{
	"collection": "products",
	"fields": {
		"app_property_1": {
			"type": "string",
			"required": true
		},
		"app_property_2": {
			"type": "int"
		}
  }
}

In the above example, the resulting model will append the field definition my_app_field to the existing products model.

Notice how there is no explicit namespace on the field object. This is intentional, as Swell handles namespace conflicts in a unique way that supports overlapping fields among apps, without causing conflicts internally or externally. It works because each API key is identified by a specific app, and data is isolated by an internal structure. App models and fields can still be accessed without an app-scoped API key, however the model API endpoint necessarily has a namespace prefix in that case. See our architecture guide for more details.

Content models

Consider content models as 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 manually, or by using the following CLI command:

swell create content

Note: 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 for the purpose of displaying in the admin dashboard, while data models are purely schema oriented for the purpose of structuring 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 will automatically enhance the underlying data model associated with that collection.

Public permissions

All model collections are private by default, but to support accessing data from the frontend API you can declare individual fields or entire models as public, along with specific query parameters that can limit the range of fields returned using a public key.

Here’s an example model with a public field.

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

Events

You can configure events on a model to trigger custom logic or integrations when specific actions occur, such as creating, updating, or deleting a record. These events can be subscribed to by webhooks and functions.

To define events on a model, you can add an events property in the model configuration file. Here's a simple example of defining events on the "things" model:

models/things.json

{
  "collection": "things",
  "label": "Things",
  "fields": {
    "name": {
      "type": "string",
      "required": true
    },
    "description": {
      "type": "string"
    },
    "status": {
      "type": "string",
      "enum": ["active", "inactive"]
    }
  },
  "events": {
    "enabled": true,
    "types": [
      { "id": "created" },
      { "id": "updated" },
      { "id": "deleted" },
      {
        "id": "activated",
        "conditions": {
          "status": "active",
          "$record": {
            "status": { "$ne": "active" }
          }
        }
      }
    ]
  }
}

In this example, we've defined three standard events: created, updated, and deleted. These events are triggered by the corresponding actions on the "things" model. Note that it's also possible to add conditions to these standard events.

Also in this example, we've added a new field called status to the "things" model with two possible values: active and inactive, and defined a custom event called activated, which is triggered when a Thing changes its status from inactive to active.

Views

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

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.