Origin is a full-fledged and functional ecommerce web app for Swell that utilizes modern JavaScript and front-end tooling. It's intended as a reference example and starter project for building custom storefronts powered by Swell. Take what you need and make it your own—without having to start from scratch.

  • Built with Nuxt.js (the Vue equivalent of Next.js).
  • Uses Tailwind CSS, so it's easy to change the design.
  • Connects to a hosted git repo for syncing code and settings with your live store.
  • Supports editable custom content types and fields in Swell's dashboard and visual storefront editor.
  • Includes page templates, sections, and components for common use cases.
  • Multi-currency and multi-language support.
  • Pre-built cart and checkout.
  • Subscriptions for physical and digital products

Add your Swell store ID, public key, and url to .env.

// Install dependencies
$ yarn install

// Serve with hot module reloading at localhost:3000
$ yarn run dev

// Build for production and start local server
$ yarn run build
$ yarn start

// Generate static build for hosting on Netlify/Render/Surge etc.
// For more details about static generation, check the Nuxt docs
$ yarn run generate

If you aren't already familiar with Vue, Nuxt, Tailwind, or Swell, these resources will get you up to speed:

For more advanced usage and packages you can use in your project:

The @nuxtjs/pwa module provides PWA functionality.

  • Sentry integration for error reporting is provided by the @nuxtjs/sentry module. All you need to do is add your DSN, either as a SENTRY_DSN env variable or on the sentry object in nuxt.config.js.
  • Any components in the /components folder are loaded automatically, so you don't need to explicitly import them.
  • Common cart methods are implemented as Vuex actions in /store/index.js
  • Swell.js is initialized and injected into the Nuxt context as $swell by the @swell/nuxt-client TODO module

For a detailed explanation of how these things work, check out Nuxt.js docs.

/config/editor.json defines the settings fields available in the 'Design & global settings' section of the theme editor in the Swell dashboard.

/config/settings.json contains the values of those settings fields, plus a read-only store object with things like your store name and currency.

The menus array in /config/editor.json defines locations/slots in the theme that can display a navigation menu and the shape of each menu tier. This config is used in the dashboard (under storefront > navigation) to show admins a menu editing UI.

/config/menus.json contains all navigation menus that have been set up in the dashboard.

Whenever store settings, theme settings, or navigation menus are changed in the dashboard, settings.json and menus.json will be updated in the remote repo. You can edit this file locally for testing purposes, but keep in mind that pulling from the remote will overwrite your changes.

Defining style properties

By default, the contents of the colors and fonts objects in settings.json are treated as style properties, with their child keys and values converted to CSS variables at build time in assets/css/variables.css. If you have additional fields that you want to generate variables for, add the keys to the module options.


If colors.primary.darkest in settings.json has a value of #222222, because colors is configured as a style property, that will generate the CSS variable --colors-primary-darkest: #222222;. If you have a field configured in editor.json with id: 'trogdor.the.burninator', the following config would convert any properties on the trogdor object to variables.

The resulting object is turned into a list of root CSS variables by the swell-editor module. You can reference these variables in tailwind.config.js or anywhere else you need to change how components are displayed.

In dev mode, these will be injected as an inline stylesheet for rapid prototyping. For production, a stylesheet will be written to /assets/css/variables.css during the build process and loaded as a global CSS file.

Style presets

If you want admins to be able to choose from several predefined style sets for colors, typography, and other design parameters, you can define them in /config/styles.json. All properties of the active style set will be merged into settings.json.

The /config/content folder stores content type definitions. Each JSON file represents a content type, which can also be referenced in other content types.

If a content type doesn't need to be referenced in multiple types (e.g., a repeatable item in a media slider), you can define the type object in the item_types value of a collection field.

name: Human-friendly label displayed in the dashboard.

description: Explanation of what the content type is intended for.

model: If a content type is only used inside another type and doesn't need to be fetched by itself, you can leave this attribute out.

There are two situations where you'll need to specify a model:

  1. Making a content type queryable
    If the content type is standalone and needs to have its own endpoint for fetching data (like pages or blog posts), the model value should be content/{pluralized_type_id} (e.g., content/pages). Note: Custom model IDs should use snake_case for consistency with system models.
  2. Content types can be used to add fields to system models like categories and products. Including the model attribute with the system model ID as the value will add a content object to each instance, with content type field nested inside. This way, custom content fields won't ever conflict with standard fields.

fields: An array of field definition objects (see below for details)

As you'd expect from a CMS, there are many different field types you can use to model and edit your content. Each field on a content type is an object containing the following attributes:

id: A unique field ID for referencing the field in code. IDs may be specified as an object path, enabling values to be nested together for convenience and clarity.


Custom fields should use snake_case for consistency with system fields. Since convention in the Vue ecosystem is to use camelCase for variable names, Swell.js will normalize object keys when sending and receiving data.

label: Human-friendly label displayed in the dashboard.

type + ui:

  • type is the type of field to use for storing the value.
  • ui (optional) is the interface displayed in the dashboard, allowing for a more appropriate editing experience and specific formatting. If omitted, the default UI for the field type will be used.

heading: For breaking up a set of fields in the dashboard. Not included in API responses.

short_text: For a small amount of plain text that fits on one line.

long_text: For a larger amount of text that spans multiple lines and may include special formatting.

number: For any kind of numerical value.

boolean: For binary values that are true or false.

select: For choosing from a list of predefined values.

lookup: For referencing objects in the system.

asset: For uploading files like images and documents.

collection: For lists of items that can be manually ordered. Ideal for flexible and repeatable content like landing pages or media sliders.

date: For inputting dates and times; saved as an ISO 8601 date string.

color: For inputting a color using a color picker UI; saved as a hex code.

tags: For Adding one or more text tags; features autocomplete.

field_group: For grouping fields together to reduce clutter in the dashboard and provide an optimal editing experience.


Fields inside groups are not nested on API responses by default, as groups are only there to improve the editing UX. However, as with any field, you can specify the child field IDs as object paths if you want to nest several fields under one key.