# Next Commerce: Storefront
> Storefront themes and Theme Kit, template objects, tags and filters, theme settings, the storefront GraphQL API, checkout links, and event tracking.
This is one of 6 domain bundles derived from the platform capability map at https://developers.nextcommerce.com/capabilities.json (generated 2026-09-03). The other bundles are listed at https://developers.nextcommerce.com/llms.txt. Merchant and operator guides are on https://docs.nextcommerce.com; the changelog is https://docs.nextcommerce.com/changelog. The Admin API contract is the OpenAPI file at https://developers.nextcommerce.com/api/admin/2024-04-01.yaml.
## Capabilities
### Storefront themes (id: storefront-themes)
The hosted storefront is rendered from a theme built with Django Template Language. Merchants install and customise themes under Storefront > Themes; developers build themes locally with Theme Kit (the ntk CLI: ntk pull, ntk push, ntk watch), starting from the Spark starter theme, and query storefront data through the GraphQL API.
Status: available. Audiences: merchant, developer. Links verified: 2026-09-03.
Merchant and operator guides (docs.nextcommerce.com):
- https://docs.nextcommerce.com/docs/build-a-store/storefront
- https://docs.nextcommerce.com/docs/build-a-store/storefront/themes
- https://docs.nextcommerce.com/docs/build-a-store/storefront/pages-and-assets
Developer guides (developers.nextcommerce.com):
- https://developers.nextcommerce.com/docs/storefront
- https://developers.nextcommerce.com/docs/storefront/themes
- https://developers.nextcommerce.com/docs/storefront/themes/theme-kit
- https://developers.nextcommerce.com/docs/storefront/themes/settings
- https://developers.nextcommerce.com/docs/storefront/themes/translations
- https://developers.nextcommerce.com/docs/storefront/themes/cdn-and-caching
- https://developers.nextcommerce.com/docs/storefront/themes/templates
- https://developers.nextcommerce.com/docs/storefront/themes/templates/objects
- https://developers.nextcommerce.com/docs/storefront/themes/templates/tags
- https://developers.nextcommerce.com/docs/storefront/themes/templates/filters
- https://developers.nextcommerce.com/docs/storefront/themes/templates/urls-and-template-paths
- https://developers.nextcommerce.com/docs/storefront/themes/guides/custom-page-templates
- https://developers.nextcommerce.com/docs/storefront/themes/guides/custom-product-templates
- https://developers.nextcommerce.com/docs/storefront/themes/guides/product-variants
- https://developers.nextcommerce.com/docs/storefront/themes/guides/product-metadata
- https://developers.nextcommerce.com/docs/storefront/themes/guides/personalized-products
- https://developers.nextcommerce.com/docs/storefront/graphql
- https://developers.nextcommerce.com/docs/storefront/event-tracking
Admin API operations, version 2024-04-01 (13):
- [GET /pages/ — Retrieve a list of pages.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/pagesList)
- [POST /pages/ — Create a new page.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/pagesCreate)
- [GET /pages/{id}/ — Retrieve a page.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/pagesRetrieve)
- [PUT /pages/{id}/ — Update an existing page.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/pagesUpdate)
- [PATCH /pages/{id}/ — Partially update an existing page.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/pagesPartialUpdate)
- [DELETE /pages/{id}/ — Delete an existing page.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/pagesDestroy)
- [GET /themes/ — Retrieve a list of themes.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/themesList)
- [POST /themes/ — Create a new theme.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/themesCreate)
- [GET /themes/{id}/ — Retrieve a theme.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/themesRetrieve)
- [DELETE /themes/{id}/ — Delete an existing theme.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/themesDestroy)
- [GET /themes/{id}/templates/ — Retrieve a list of templates in an existing theme.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/themesTemplatesRetrieve)
- [POST /themes/{id}/templates/ — Create a new template in an existing theme.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/themesTemplatesCreate)
- [DELETE /themes/{id}/templates/ — Delete an existing template in an existing theme.](https://developers.nextcommerce.com/docs/admin-api/reference/storefront/themesTemplatesDestroy)
AI agent skills:
- [next-theme-dev](https://github.com/NextCommerceCo/skills/tree/main/next-theme-dev)
- [next-theme-figma](https://github.com/NextCommerceCo/skills/tree/main/next-theme-figma)
### Checkout links (id: checkout-links)
Prebuilt URLs that open the storefront checkout with products, quantities, and attribution already applied, for use from ads, emails, and campaign pages.
Status: available. Audiences: merchant, developer. Links verified: 2026-09-03.
Merchant and operator guides (docs.nextcommerce.com):
- https://docs.nextcommerce.com/docs/features/offers/shareable-coupon-links
Developer guides (developers.nextcommerce.com):
- https://developers.nextcommerce.com/docs/storefront/checkout-links
## Pages
The full text of every developer page cited above, in the order listed.
# Storefront (https://developers.nextcommerce.com/docs/storefront)
The Next Commerce storefront is a flexible, customizable front-end layer for your ecommerce business. Whether you're building a completely custom storefront or enhancing an existing theme, this section will guide you through the tools and features available to developers.
### Themes [#themes]
Themes allow you to fully control the look and feel of your storefront using modern front-end technologies. Each theme includes layouts, templates, stylesheets, and scripts, giving you full creative freedom to build a branded customer experience.
* Customize homepage, products, catalog, and pages
* Easily manage theme assets (CSS, JS, images)
* Customize themes via the dashboard or CLI (Theme Kit)
Learn how to [build and manage your theme →](https://developers.nextcommerce.com/docs/storefront/themes)
### Event Tracking [#event-tracking]
Capture user behavior, conversion events, and key storefront interactions with built-in event tracking tools.
* Track add-to-cart, purchases, and other standard ecommerce events
* Hook into page views, checkout events, and custom triggers
* Integrate storefront events with external platforms
Learn how to [implement tracking for your storefront →](https://developers.nextcommerce.com/docs/storefront/event-tracking)
### Storefront GraphQL API [#storefront-graphql-api]
Power deeper customizations, dynamic content loading, and headless experiences using our Storefront GraphQL API.
* Fetch products, cart data, and more in real-time.
* Create custom functionality such as cart upsells.
Learn how to [query your storefront data →](https://developers.nextcommerce.com/docs/storefront/graphql)
# Themes (https://developers.nextcommerce.com/docs/storefront/themes)
> **Tip:** We highly recommend using Theme Kit to manage your store theme for the best developer experience from your favorite IDE. [Read the Theme Kit guide](https://developers.nextcommerce.com/docs/storefront/themes/theme-kit) — installation, configuration, and every `ntk` command.
### Layout & Structure [#layout--structure]
The Storefront theme framework has a set guideline for the base directories of your theme for your assets, html, and settings.
```bash title="Storefront Theme Structure"
theme
├── assets
├── checkout
├── configs
├── layouts
├── locales
├── partials
├── sass
└── templates
```
### Assets [#assets]
The assets directory is used to upload static asset files used in the theme such as images, stylesheets, web fonts, and javascript files. The assets directory works in conjunction with the [`asset_url` template filter](https://developers.nextcommerce.com/docs/storefront/themes/templates/filters#asset_url) to render the full path on your storefront.
```jinja title="Example link in template to /assets/css/style.css"
{{ 'css/style.css'|asset_url }}
```
### Configs [#configs]
The configs directory is used to store your theme settings options and also the settings data as they should be configured with the theme.
* `settings_schema.json` is used to generate the theme settings form
* `setting_data.json` is used data storage for the the theme settings
```bash title="Config Directory"
configs
├── settings_data.json
└── settings_schema.json
```
[See Theme Settings Guide](https://developers.nextcommerce.com/docs/storefront/themes/settings)
### Locales [#locales]
The `locales` directory is used to for storefront theme translation json files. The translation files are used in conjunction with the translation template tag to support multiple languages for your storefront.
Translation files should be named according to the ISO 639-1 2 letter language code standard. The default or fallback language should be denoted with a .default in the file name as shown below. See the [Translations guide](https://developers.nextcommerce.com/docs/storefront/themes/translations) for more examples on how to localize your theme content.
```bash title="Locale Files Example"
locales
├── en.default.json
├── de.json
├── es.json
├── it.json
└── fr.json
```
[See Translations Guide](https://developers.nextcommerce.com/docs/storefront/themes/translations)
### Layouts [#layouts]
The `layouts` directory is used to store base templates that are then extended from in view specific templates, see extends and block template tags for more on template inheritance. See the [`extends` template tag](https://developers.nextcommerce.com/docs/storefront/themes/templates/tags#extends--block) for more on template inheritance.
```bash title="Layouts Directory Example"
layouts
└── base.html
```
### Partials [#partials]
The partials directory is used to store reusable which are reusable snippets of code that can be used in tandem with the include template tag for reuse across many templates. See the includes template tag for more on template inheritance with partials.
```bash title="Partials Directory Example"
partials
├── header.html
├── footer.html
└── pagination.html
```
```jinja title="Example Partial Include Another Template"
{% include "partials/footer.html" %}
```
### Templates [#templates]
The templates directory is used to store all templates for a theme, see [URLs and Template Paths](https://developers.nextcommerce.com/docs/storefront/themes/templates/urls-and-template-paths) for reference.
```bash title="Templates Directory Example"
templates
├── 403.html
├── 404.html
├── 500.html
├── blog
│ ├── index.html
│ └── post.html
├── cart.html
├── catalogue
│ ├── category.html
│ ├── index.html
│ └── product.html
├── index.html
├── pages
│ └── page.html
├── reviews
│ ├── form.html
│ ├── index.html
│ └── review.html
├── search.html
└── support
├── article.html
├── category.html
└── index.html
```
### Sass [#sass]
The sass directory accepts scss files for use in in a theme. See Theme Kit for more details on local sass compiling.
> **Warning:** Sass files are not automatically compiled in the platform and must be compiled to css files locally for use in templates from the assets directory.
### Theme Kit [#theme-kit]
[Theme Kit](https://github.com/NextCommerceCo/theme-kit) is a command line tool for developers to build an maintain storefront themes programmatically, allowing theme developers to:
* Work on theme templates and assets using their local code editor or favorite IDE.
* Use git version control to work on a theme collectively with many theme collaborators.
* Use a pipeline to manage deployments of theme updates.
> **Tip:** See the [Theme Kit guide](https://developers.nextcommerce.com/docs/storefront/themes/theme-kit) for installation, configuration, and commands. Source: [GitHub](https://github.com/NextCommerceCo/theme-kit).
# Theme Kit (https://developers.nextcommerce.com/docs/storefront/themes/theme-kit)
[Theme Kit](https://github.com/NextCommerceCo/theme-kit) is a command line tool for developers to build and maintain storefront themes programmatically, allowing theme developers to:
* Work on theme templates and assets using their local code editor or favorite IDE.
* Use git version control to work on a theme collectively with many theme collaborators.
* Use a pipeline to manage deployments of theme updates.
[See Full Instructions on Github](https://github.com/NextCommerceCo/theme-kit) or [Install Theme Kit from PyPi](https://pypi.org/project/next-theme-kit/)
### Installation [#installation]
Theme Kit is a python package available on [PyPi](https://pypi.org/project/next-theme-kit/)
If you already have `python` and `pip`, install with the following command:
```bash title="Installation"
pip install next-theme-kit
```
#### Mac OSX Requirements [#mac-osx-requirements]
See how to install `python` and `pip` with [HomeBrew](https://docs.brew.sh/Homebrew-and-Python#python-3x). Once you have completed this step you can install using the `pip` instructions above.
#### Windows Requirements [#windows-requirements]
* **Option 1 (Recommended)** - Windows 10 and above feature WSL (Windows Subsystem for Linux) which provides a native Linux environment, see how to [Install WSL with Ubuntu](https://docs.microsoft.com/en-us/windows/wsl/install). Once you have installed WSL, follow the [best practice guides to configure and use with VS Code](https://docs.microsoft.com/en-us/windows/wsl/setup/environment) and then follow the `pip` instructions above to install Theme Kit.
* **Option 2** - Installing `python` in Windows natively can be done with through the [Windows App Store](https://apps.microsoft.com/store/detail/python-39/9P7QFQMJRFP7?hl=en-us\&gl=us). Recommend using [Windows Powershell](https://apps.microsoft.com/store/detail/powershell/9MZ1SNWT0N5D?hl=en-us\&gl=us). This route is a little more tricky and some knowledge on how to manage python in windows will be required.
> **Tip:** **Use Python Virtual Environments** - For Mac, Windows, and Linux, it's a best practice to use a Python Virtual Environment to isolate python packages and dependencies to reduce potential conflicts or errors, [more on creating a Python Virtual Environment](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/).
### Setup [#setup]
Connect `ntk` to a store in three steps.
#### 1. Create the API Key [#1-create-the-api-key]
Store authentication uses [OAuth 2.0](https://auth0.com/intro-to-iam/what-is-oauth-2/) and requires creating a store OAuth App with the `themes:read` and `themes:write` permissions.
1. In the Storefront admin, go to **Settings > API Access**.
2. Click **Create App**.
3. Give the app a name and assign a user.
4. In the **Permissions** tab, enable `themes:read` and `themes:write`.
5. **Save**. Copy the generated API key — you will need it in the next step.
#### 2. Configure Theme Kit [#2-configure-theme-kit]
`ntk` reads its connection settings from two places: command flags (`--apikey`, `--store`, `--theme_id`) and the `config.yml` file in your theme directory. You do not need to create `config.yml` by hand — `ntk checkout` and `ntk init` write it for you, and after that commands run without flags:
```yaml title="config.yml (written by ntk checkout / ntk init)"
development:
apikey:
store: https://{store}.29next.store
theme_id:
```
> **Warning:** Keep the API key out of source control. Do not commit `config.yml` to git if it contains the key.
> **Note:** `config.yml` supports multiple environments. Commands use the `development` entry by default; pass `-e` / `--env` to target another environment (e.g. `ntk push --env=production`). The `[development]` prefix in command output is the active environment.
#### 3. Connect to a Theme [#3-connect-to-a-theme]
Work from a copy of an existing theme rather than an empty directory — a complete theme is the reference for the required directories, templates, and settings.
**Work on a theme already on the store** — `ntk checkout` downloads the theme into your current directory and writes `config.yml`:
```bash
ntk checkout --theme_id= --apikey="" --store="https://{store}.29next.store"
```
**Add a new theme to the store** — start from a copy of an existing theme, such as the [Spark](https://github.com/NextCommerceCo/spark) starter theme, then register it as a new theme with `ntk init` and upload the files with `ntk push`:
```bash
ntk init --name="" --apikey="" --store="https://{store}.29next.store"
ntk push
```
### Usage [#usage]
With the package installed, you can now use the commands inside your theme directory and work on a storefront theme.
| Command | Description |
| -------------- | --------------------------------------------------------------- |
| `ntk init` | Initialize a new theme |
| `ntk list` | List all available themes |
| `ntk checkout` | Checkout an existing theme |
| `ntk pull` | Download existing theme or theme file |
| `ntk push` | Push current theme state to store |
| `ntk watch` | Watch for local changes and automatically push changes to store |
| `ntk sass` | Process sass to css, see [Sass Processing](#sass-processing) |
#### Browse Store Themes [#browse-store-themes]
To see what themes exist on the store, run `ntk list` to print the theme ID and name of each, with the active theme marked.
```bash
ntk list
```
Output looks like:
```
[development] Available themes:
[development] [42] Spring Launch
[development] [43] Holiday Promo (Active)
```
If you do not have a `config.yml`, also pass `--apikey` and `--store`.
#### Work on an Existing Theme [#work-on-an-existing-theme]
To start working on a theme that already exists on the store, `ntk checkout` downloads it into your directory and writes `config.yml` with the theme ID.
```bash
ntk checkout --theme_id=
```
`--theme_id` / `-t` is required. If you do not have a `config.yml`, also pass `--apikey` and `--store`:
```bash
ntk checkout --theme_id= --apikey="" --store="https://{store}.29next.store"
```
`ntk checkout` differs from `ntk pull` in one way: `checkout` writes `config.yml` so the directory is ready for subsequent `ntk push` / `ntk watch` runs; `pull` downloads the same files without writing `config.yml`.
#### Add a New Theme to the Store [#add-a-new-theme-to-the-store]
`ntk init` registers your current directory as a new theme on the store and writes a `config.yml`. It does not download or scaffold any files — run it inside an existing theme codebase, then `ntk push` to upload the files.
> **Warning:** Building a theme from an empty directory is not advised. Start from a copy of a complete theme — the [Spark](https://github.com/NextCommerceCo/spark) starter theme (Tailwind CSS), the older Bootstrap-based [Intro Bootstrap](https://github.com/NextCommerceCo/intro-bootstrap) or an existing theme from your store via [`ntk checkout`](#work-on-an-existing-theme).
```bash
ntk init --name=""
```
`--name` / `-n` is required. If you do not have a `config.yml` yet, also pass `--apikey` and `--store`:
```bash
ntk init --name="" --apikey="" --store="https://{store}.29next.store"
```
On success, `ntk init` logs the new theme ID and name, and persists the theme ID into `config.yml` so subsequent commands can omit `--theme_id`.
#### Sync Files to the Store [#sync-files-to-the-store]
To sync files between your local directory and the store, use `ntk push` to upload and `ntk pull` to download. Both upload or download the whole theme by default, and both accept file paths as positional arguments to limit the operation to specific files.
> **Note:** File paths are relative to the theme root. `ntk push` only uploads files inside the theme directories (`assets`, `checkout`, `configs`, `layouts`, `locales`, `partials`, `sass`, `templates`) with valid theme file extensions — a path outside of them is skipped silently, not reported as an error.
**Push a single file**
```bash
ntk push templates/index.html
```
**Push a subset of files**
```bash
ntk push templates/index.html assets/main.css
```
**Pull a single file**
```bash
ntk pull templates/index.html
```
**Pull a subset of files**
```bash
ntk pull templates/index.html assets/main.css
```
#### Watch for File Changes [#watch-for-file-changes]
`ntk watch` monitors your theme directory and automatically pushes changed files to the store. Use it while you develop — save a file and the change is uploaded moments later.
```bash
ntk watch
```
On start, `ntk watch` logs the store, theme ID, a preview-theme URL, and the directory it is watching. Press `Ctrl + C` to stop.
> **Note (Verify Changes on the Network Domain):** After each upload, open the affected route on `https://{store}.29next.store` and verify the served HTML, expected assets, and behavior. Do not use a mapped public storefront domain to decide whether a push succeeded. Check the public domain only after network-domain verification.
> **Warning:** Deletes sync too — deleting a local file while `ntk watch` is running deletes that file from the theme on the store.
> **Note:** `ntk watch` watches the current directory tree (subdirectories included) and only uploads files with valid theme extensions. It does not accept file arguments. To scope changes to specific files, run `ntk push` with file paths instead.
#### Sass Processing [#sass-processing]
Theme kit includes support for Sass processing via [Python Libsass](https://sass.github.io/libsass-python/). Sass processing includes support for variables, imports, nesting, mixins, inheritance, custom functions, and more.
> **Warning:** Sass processing is only supported on local, files in the `sass` directory are uploaded to your store for storage but cannot be edited in the store theme editor.
**How it works**
1. Put `scss` files in top level `sass` directory.
2. Run `ntk sass` or `ntk watch` to process theme `sass` files.
3. Top level `scss` files will be processed to `css` files in the asset directory with the same name.
**Example Theme with Sass Structure**
```text title="Sass Processing"
├── assets
│ ├── main.css // reference this asset file in templates
├── sass
│ ├── _base.scss
│ ├── _variables.scss
│ └── main.scss // processed to assets/main.css
```
# Theme Settings (https://developers.nextcommerce.com/docs/storefront/themes/settings)
### Introduction [#introduction]
Theme settings are the power behind the dashboard theme editor experience allowing users to customize the look and feel of their storefront without needing to know how to code.
### Theme Settings Location [#theme-settings-location]
Theme settings consist of two JSON files in the `/configs` directory.
```
configs
└── settings_schema.json
└── settings_data.json
```
* `settings_schema.json` - Used to create the settings schema to create settings shown in the dashboard theme editor.
* `settings_data.json` - Used to store theme settings values for access in templates for rendering.
### Using Settings in Templates [#using-settings-in-templates]
Settings are passed to templates settings context variable allowing you to access settings values by their name. See example below of changing the layout by conditionally adding a class based on a radio setting.
**Settings Schema**
```json title="Using Settings in Templates"
{
"General": {
"Settings": [
{
"name": "store_name",
"label": "Store Name",
"help_text": "Public name of your store.",
"type": "text",
"max_length": 250,
"required": 1,
"default": "Store Name"
},
{
"name": "layout",
"label": "Layout Style",
"help_text": "Control the layout style.",
"type": "radio",
"options": [
{
"name": "Boxed",
"value": "boxed"
},
{
"name": "Full Width",
"value": "full"
}
],
"default": "boxed"
}
]
}
}
```
**Template**
```html title="Template"
Welcome to {{ settings.store_name }}!
Conditionally boxed or full width content
```
### Attribute Reference [#attribute-reference]
| Attribute | Required | Description |
| ------------ | -------- | ---------------------------------------------------------------------------------------------------- |
| `type` | Yes | Type of form input, see Schema Input Types. |
| `name` | Yes | Name of the setting and key for access in template settings object variable. |
| `label` | Yes | Theme settings form input label. |
| `help_text` | No | Theme settings form input help text that shows below the input. |
| `required` | No | JSON boolean, accepts true or false, false by default. |
| `default` | No | Default value for the setting. |
| `options` | No | List of `key:value` pairs for options. Applicable to radio and select field types for their choices. |
| `max_length` | No | Applicable to `text` field types to limit the length of text input. |
| `max_value` | No | Applicable to number field types to limit the max value. |
| `min_value` | No | Applicable to number field types to set a min value. |
## Schema Input Types [#schema-input-types]
Schema input types map to input fields that will be rendered in the settings form in the dashboard.
### checkbox [#checkbox]
A `checkbox` setting outputs a checkbox field input for use cases such as toggling features on and off.
When accessing a `checkbox` field value in a template, it returns boolean.
```json title="Example checkbox setting"
{
"name": "enable_cookie_msg",
"label": "Enable Cookie Message Pop",
"help_text": "Enable cookie message to site visitors.",
"type": "checkbox",
"default": true
}
```
### color [#color]
A `color` setting outputs a color picker field allowing the user to chose a color for cases such as customizing font and button styles.
When accessing a `color` field value in a template, it returns a hex value as a string.
```json title="Example color setting"
{
"type": "color",
"name": "btn_primary_color",
"label": "Primary Button Color",
"help_text": "Primary color for buttons.",
"default": ""
}
```
### css [#css]
A `css` setting outputs an css code editor allowing the user to add custom css in a nicely formatted editor for cases such as custom css styles.
When accessing a `css` field value in a template, it returns the a string with the css pre-wrapped with `` tags.
```json title="Example css setting"
{
"type": "css",
"name": "custom_css",
"label": "Custom CSS",
"help_text": "Example css input."
}
```
### email [#email]
A `email` setting outputs a email field allowing the user to add validated email text for cases of showing a contact email.
When accessing a `email` field value in a template, it returns a string.
```json title="Example email setting"
{
"type": "email",
"name": "contact_email_address",
"label": "Public contact email address.",
"help_text": "Email to show in site footer.",
"default": ""
}
```
### file [#file]
A `file` setting outputs a file upload input field allowing the user to upload files for scenarios such as a homepage banner background image.
When accessing a `file` field value in a template, it returns a full CDN link to the uploaded file.
```json title="Example file setting"
{
"type": "file",
"name": "logo",
"label": "Store Logo",
"help_text": "Primary logo used throughout the site.",
"default": "uploads/logo.png"
}
```
### html [#html]
A `html` setting outputs an html code editor allowing the user to add custom html in a nicely formatted editor for cases such as code snippets or video embeds.
When accessing a `html` field value in a template, it returns the html content string.
```json title="Example html setting"
{
"type": "html",
"name": "custom_html",
"label": "Custom HTML",
"help_text": "Example html input."
}
```
### image\_picker [#image_picker]
An `image_picker` setting outputs outputs an image picker modal making all uploaded image assets available to select from.
```json title="Example image picker setting"
{
"name": "example_image_picker",
"label": "Example Image Field",
"type": "image_picker",
"required": false
}
```
### menu [#menu]
A `menu` setting field outputs a dropdown select field to choose from the available navigation menus.
When accessing a `menu` setting value in a template, it returns a menu object allowing you to access the menus items. See [menus](https://developers.nextcommerce.com/docs/storefront/themes/templates/objects#menus) object details for working with menus in templates.
```json title="Example menu setting"
{
"name": "header_menu",
"label": "Header Menu",
"type": "menu",
"required": true,
"help_text": "Header Menu"
}
```
### multi-select [#multi-select]
A `multi-select` setting outputs a multi-select field that can allows users to select multiple values from a predefined list of options.
When accessing a `multi-select` field value in a template, it returns a list of values that have been saved.
```json title="Example multi-select setting"
{
"type": "select",
"multi-select": true,
"name": "accepted_payment_methods",
"label": "Accepted Payment Methods",
"help_text": "Control which payment methods are shown.",
"options": [
{
"name": "Visa",
"value": "visa"
},
{
"name": "Master Card",
"value": "mastercard"
},
{
"name": "American Express",
"value": "amex"
},
{
"name": "Paypal",
"value": "paypal"
},
{
"name": "Klarna",
"value": "klarna"
}
],
"default": [
"visa",
"mastercard"
]
}
```
### number [#number]
A `number` setting field outputs a standard number input field allowing users to input a number respecting the optionally available min and max values.
When accessing a `number` setting value in a template, it's returned as an integer.
```json title="Example number setting"
{
"type": "number",
"name": "homepage_testimonials_count",
"label": "Homepage Number Testimonials to Show",
"help_text": "Control the number of homepage testimonials to show",
"max_value": 10,
"min_value": 0,
"default": 3
}
```
### page [#page]
A `page` setting field outputs a dropdown select field to choose from the available pages.
When accessing a `page` setting value in a template, it returns a page object. See [page](https://developers.nextcommerce.com/docs/storefront/themes/templates/objects#page) object details for working with pages in templates.
```json title="Example page setting"
{
"type": "page",
"name": "page_setting",
"label": "Example Setting Page",
"help_text": "Link to page configured from settings."
}
```
### product [#product]
A `product` setting field outputs a dropdown select field to choose from the available products in the store catalogue.
When accessing a `product` setting value in a template, it returns a product object. See [product](https://developers.nextcommerce.com/docs/storefront/themes/templates/objects#product) object details for working with products in templates.
```json title="Example product setting"
{
"name": "hero_product",
"label": "Hero Product",
"type": "product",
"help_text": "Hero product on homepage banner.",
"required": false
}
```
### products [#products]
A `products` setting field outputs a multi-select field to choose from the available products in the store catalogue.
When accessing a `products` setting value in a template, it returns a list of products to iterate through. See [product](https://developers.nextcommerce.com/docs/storefront/themes/templates/objects#product) object details for working with products in templates.
```json title="Example products setting"
{
"name": "featured_products",
"label": "Featured Products",
"type": "products",
"help_text": "Featured products for homepage."
}
```
### product\_category [#product_category]
A `product_category` setting field outputs a dropdown select field to choose from the available product categories.
When accessing a `product_category` setting value in a template, it returns a product category object. See [product category](https://developers.nextcommerce.com/docs/storefront/themes/templates/objects#product_category) object details for working with product categories in templates.
```json title="Example featured_products setting"
{
"name": "featured_products",
"label": "Featured Product Category",
"type": "product_category",
"help_text": "Featured product category for homepage"
}
```
### product\_categories [#product_categories]
A `product_categories` setting field outputs a multi-select field to choose from the available product categories.
When accessing a `product_categories` setting value in a template, it returns a list of product categories to iterate through. See [product category](https://developers.nextcommerce.com/docs/storefront/themes/templates/objects#product_category) object details for working with product categories in templates.
```json title="Example product_categories setting"
{
"name": "top_product_categories",
"label": "Top Product Categories",
"type": "product_categories",
"help_text": "Featured product categories for homepage"
}
```
### radio [#radio]
A `radio` setting outputs a radio option field that can be used in option selection scenarios such as alignment or layout style.
When accessing a `radio` setting value in a template, it's returned as a string.
```json title="Example radio setting"
{
"type": "radio",
"name": "layout",
"label": "Layout Style",
"help_text": "Control the layout style.",
"options": [
{
"name": "Boxed",
"value": "boxed"
},
{
"name": "Full Width",
"value": "full"
}
],
"default": "boxed"
}
```
### range [#range]
A `range` setting outputs a slider that can be used to a varying numerical value such as font size, number of columns or opacity.
When accessing a `range` setting value in a template, it's returned as an integer.
```json title="Example range setting"
{
"type": "range",
"name": "slider_range_field",
"label": "Headings font size",
"help_text": "",
"min": 0,
"max": 50,
"step": 1,
"unit": "px",
"required": true,
"default": 25
}
```
### richtext [#richtext]
A `richtext` setting displays a WYSIWYG editor with basic text formatting options allowing users to input and format text content.
When accessing a `richtext` setting value in a template, it's returned as a string.
```json title="Example richtext setting"
{
"type": "richtext",
"name": "richtext_content",
"label": "Description Content",
"help_text": "Example rich text input field."
}
```
### select [#select]
A `select` setting outputs a dropdown option select field that can be used in option selection scenarios such as alignment or layout style.
When accessing a `select` setting value in a template, it's returned as a string.
```json title="Example select setting"
{
"type": "select",
"name": "header_style",
"label": "Header Style",
"help_text": "Choose header layout style.",
"options": [
{
"name": "Full Width",
"value": "full"
},
{
"name": "Boxed",
"value": "boxed"
},
{
"name": "Overlay",
"value": "overlay"
}
],
"default": "full"
}
```
### text [#text]
A `text` setting outputs a single line input field that can be used in scenarios such as the banner heading text on the homepage.
When accessing a `text` setting value in a template, it's returned as a string.
```json title="Example text setting"
{
"type": "text",
"name": "store_name",
"label": "Store Name",
"help_text": "Public name for your store.",
"max_length": 250,
"required": true,
"default": "My New Store Name"
}
```
### textarea [#textarea]
A `textarea` setting outputs a multi-line textarea input field that can be used in scenarios such as the banner sub-heading text on the homepage.
When accessing a `textarea` setting value in a template, it's returned as a string.
```json title="Example textarea setting"
{
"type": "textarea",
"name": "description",
"label": "Description",
"help_text": "Example input textarea",
"default": "Example long multi-line sub-heading text for the banner."
}
```
### url [#url]
A `url` setting outputs an input url type field that accepts fully qualified urls that can be used for relative paths or external url links.
When accessing a `url` setting value in a template, it's returned as a string.
```json title="Example url setting"
{
"type": "url",
"name": "social_link",
"label": "Social Media Link",
"help_text": "Link to your social media page.",
"default": ""
}
```
# Translations (https://developers.nextcommerce.com/docs/storefront/themes/translations)
Theme templates can be fully localized with translations so that your store visitors are shown content in their local language. Use the t (translation) tag in your templates to access string translations in the locale files. Learn more about the [t tag](https://developers.nextcommerce.com/docs/storefront/themes/templates/tags#t) and theme Locale files.
### Using Translations in Practice [#using-translations-in-practice]
The `t` tag accepts an initial argument that is the key reference to the translation string in a locale file.
**Template**
```jinja title="Using Translations in Practice"
```
### Passing Variable Arguments to Translations [#passing-variable-arguments-to-translations]
You can pass multiple named arguments to translations through the `t` tag used in the translation.
**Template**
```jinja title="Passing Variable Arguments to Translations"
{% t 'customer.profile.welcome_msg' with name=request.user.first_name %}
```
**en.default.json**
```json title="Passing Variable Arguments to Translations"
{
"customer": {
"welcome_message": "Hi {{ name }}, welcome to your account!"
}
}
```
**Result**
```html title="Result"
Hi John, welcome to your account!
```
### Pluralization Support [#pluralization-support]
The t tag accepts two arguments for pluralization:
* Pass the count argument with a value for cardinal pluralization, ie 1, 2, 3, 4.
* Pass the index argument with a value for ordinal pluralization, ie First, Second, Third, Forth.
Pluralization rules follow [Unicode CLDR](https://github.com/unicode-org/cldr) specification, available keys include:
* `one`
* `other`
* `two`
* `zero`
* `few`
* `many`
#### Cardinal Pluralization [#cardinal-pluralization]
Cardinal pluralization can be used to display different translations based on the value passed to `count`.
**Template**
```jinja title="Cardinal Pluralization"
{% t 'customer.notifcations.total' with count=notification.count %}
```
**en.default.json**
```json title="Cardinal Pluralization"
{
"customer": {
"notifcations": {
"one": "You have {{ count }} notification.",
"other": "You have {{ count }} notifications.",
"zero": "You don't have any notifications."
}
}
}
```
**Result**
```html title="Result"
You have 1 notification.
You have 3 notifications.
You don't have any notifications.
```
#### Ordinal Pluralization [#ordinal-pluralization]
Ordinal pluralization can be used to display different translations based on the index value to display the ordering of an object.
**Template**
```jinja title="Ordinal Pluralization"
{% t 'customer.orders.orders_msg' with index=customer.orders.count %}
```
**en.default.json**
```json title="Ordinal Pluralization"
{
"customer": {
"orders_msg": {
"one": "Congrats on your {{ index }}st order!",
"two": "Congrats on your {{ index }}nd order!",
"few": "Congrats on your {{ index }}rd order!",
"other": "Congrats on your {{ index }}th order!"
}
}
}
```
**Result**
```html title="Result"
Congrats on your 1st order!
Congrats on your 2nd order!
Congrats on your 3rd order!
Congrats on your 4th order!
```
# Storefront CDN & Caching (https://developers.nextcommerce.com/docs/storefront/themes/cdn-and-caching)
Storefront leverages CDNs and many caching strategies to ensure fast performant user experiences for your end customers.
> **Note (Use Network Domain while Building Themes):** Always use the store network domain `https://{store}.29next.store` when developing, previewing, debugging, and verifying themes. Do not use a mapped public storefront domain to decide whether a theme change landed.
### Asset CDN [#asset-cdn]
All merchant uploaded media assets and theme assets are loaded from our CDN for the fastest performance.
* **Media** - Links to uploaded media should always use the `cdn.29next.store`
* **Theme Assets** - Theme assets should use the [asset\_url](https://developers.nextcommerce.com/docs/storefront/themes/templates/filters#asset_url) in templates which always generates a full CDN link on the storefront.
### Full Page Caching [#full-page-caching]
All pages on storefront are cached for 5 minutes to ensure popular pages are as fast as possible for customers and minimal impact on the overall platform load.
* User is Anonymous (unauthenticated).
* Domain is a merchant mapped domain.
* Page is not dynamic, ie `/cart/`, `/checkout/`, `/accounts/` do not use full page caching.
> **Tip (Verify the Network Domain First):** Confirm the latest theme on `https://{store}.29next.store` first. After it is correct there, check the mapped public storefront domain as a final customer-path smoke test.
### Template Caching [#template-caching]
Themes use many templates ie `layouts`, `partials`, and `assets` that when compiled together create amazing customer experiences. Templates are cached in memory to reduce database queries when compiling templates into the full html response.
Updating a template through the dashboard or [Theme Kit](https://developers.nextcommerce.com/docs/storefront/themes/theme-kit) should automatically purge the cache for you to see your latest changes on the network domain, see notes above.
> **Warning:** There are a few cases wherein a form on the frontend needs to use a `{% csrf_token %}` field to secure submission to the backend. The platform core JS will automatically replace `{% csrf_token %}` that are in cached versions of pages to ensure the forms still work.
>
> **It is advisable to not implement custom templates that require `{% csrf_token %}`, we recommend the [Storefront GraphQL API](https://developers.nextcommerce.com/docs/storefront/graphql) instead.**
# Templates (https://developers.nextcommerce.com/docs/storefront/themes/templates)
### Introduction [#introduction]
The storefront theme templates language is designed to be both powerful and easy to use. If you have any exposure to working with other text-based template languages such as Jinja2 or Liquid, you should feel right at home.
> **Tip:** The storefront theme template system provides **tags, filters** and **variables** for control flow logic inside of a template.
### Variables [#variables]
Variables look like this: `{{ variable }}` and contain the content the template uses to render to the page. Variables contain a dictionary structure of content and use . notation to access attributes.
**Template**
```jinja title="Variables"
Hello {{ customer.name }} !
```
**Result**
```html title="Variables"
Hello John!
```
### Filters [#filters]
Filters allow you to modify the output of a variables and look like this `{{ customer.name|title }}`. This would display the value of `{{ customer.name }}` after being filtered there the title filter to make format the string to title case. See built-in filter reference.
**Template**
```jinja title="Filters"
Hello {{ customer.name|title }}!
```
**Result**
```html title="Result"
Hello John!
```
### Tags [#tags]
Tags can do many things such as control flow, iterations, template inheritance, and theme translations. Tags look like this `{% tag %}` . [See built-in tag reference](https://developers.nextcommerce.com/docs/storefront/themes/templates/tags).
**Template**
```jinja title="Tags"
{% if products %}
{% for product in products %}
{{ product.title }}
{% endfor %}
{% else %}
No products found.
{% endif %}
```
**Result**
```html title="Result"
Product A
Product B
Product C
```
Using these core building blocks you can create fully customized shopping experiences for customers.
# Object Reference (https://developers.nextcommerce.com/docs/storefront/themes/templates/objects)
Objects are template variables you can use to dynamically populate templates in your storefront theme. See documentation below and details of available template objects and their properties.
## Global Objects [#global-objects]
Global objects are available across all templates and pages enabling theme developers to create dynamic custom pages powered by the store data.
### currencies [#currencies]
Returns a list of active storefront currencies you can iterate over, see [currency](#currency).
```jinja title="Example Storefront Change Currency Form"
{% if currencies and currencies|length > 1 %}
{% endif %}
```
### languages\_active\_storefront [#languages_active_storefront]
Returns a list of active storefront languages you can iterate over, see [language](#language).
```jinja title="Example Storefront Change Language Form"
{% if languages_active_storefront %}
{% endif %}
```
### menus [#menus]
Allows you to access a menu's items by its code to iterate over to generate a menu from the backend, see [menu items](#items-menu). Menus are configured in the dashboard at **Storefront > Navigation**.
```jinja title="Example Dynamic Menu"
{% for item in menus.header_menu.items %}
{% if item.level > 0 %}
{% endif %}
{% endfor %}
```
> **Tip:** Storefront Menus can be up to 3 levels, ensure your custom menu supports 2 nested menu item levels, see child and grandchild above.
### products [#products]
Returns a list of products you can iterate over, see [product](#product).
```jinja title="Example Storefront Products Query and Loop"
{% where products 'title' 'contains' 'featured' as products_filtered %}
{% for product in products_filtered %}
{% with image=product.primary_image %}
{% image_thumbnail image.original "350x350" crop="center" upscale=True as thumb %}
{% endwith %}
{% purchase_info_for_product request product as session %}
{% if session.price.exists %}
{{ session.price.price|currency:session.price.currency }}
{% else %}
{% endfor %}
```
### product\_categories [#product_categories]
Returns a list of product categories you can iterate over, see [product\_category](#product_category).
```jinja title="Example Storefront Product Categories Query and Loop"
{% where product_categories 'id' 'exact' 1 as homepage_categories %}
{% for category in homepage_categories %}
{% with image=category.image %}
{% if image %}
{% image_thumbnail image "350x350" crop="center" upscale=True as thumb %}
{% endif %}
{% endwith %}
{% endfor %}
```
### posts [#posts]
Returns a list of blog posts you can iterate over, see [post](#post).
```jinja title="Example Storefront Recent Blog Posts Query and Loop"
{% for post in posts|slice:"3" %}
{% with image=post.featured_image %}
{% if image %}
{% image_thumbnail image "400x250" upscale=False crop="top" as thumb %}
{% endif %}
{% endwith %}
{% endfor %}
```
### post\_categories [#post_categories]
Returns a list of post categories you can iterate over, see [post\_category](#post_category).
```jinja title="Example Storefront Post Categories Query and Loop"
```
### privacy\_policy [#privacy_policy]
Content from store Privacy Policy settings, typically used in a "Privacy Policy" page to automatically pull content in from settings.
> **Tip:** Store policies are configured in the dashboard at **Settings > Policies**. The content entered there is automatically available as global template variables.
```jinja title="privacy_policy"
{{ privacy_policy }}
```
### request [#request]
The current session active request context.
```jinja title="Example Request Object Usage"
```
| Property | Type | Description |
| --------------- | ------ | ------------------------------------------------- |
| `get_host` | String | Current host domain. |
| `path` | String | Current url path. |
| `COUNTRY_CODE` | String | Current active geo country code, see [geo](#geo). |
| `CURRENCY_CODE` | String | Current active currency code. |
| `LANGUAGE_CODE` | String | Current active language code. |
### settings [#settings]
Theme settings object with stored theme settings values as properties. See [theme settings](https://developers.nextcommerce.com/docs/storefront/themes/settings) docs.
```jinja title="Example Colors Styles From Theme Settings"
```
### store [#store]
Returns the store object with general information about the store and the contact details.
```jinja title="Example Store Object Usage"
{{ store.legal_name }}
{{ store.address.line_1 }}
{% if store.address.line_2 %}{{ store.address.line_2 }} {% endif %}
{{ store.address.city }}, {{ store.address.state }} {{ store.address.postcode }}
{{ store.address.country }}
```
| Property | Type | Description |
| ---------------------- | ------ | ----------------------------------------------------- |
| `address` | object | The store address object see [address](#address). |
| `branding` | object | The store branding object, see [branding](#branding). |
| `name` | String | General name of the store defined in settings. |
| `tagline` | String | Store tagline defined in settings. |
| `legal_name` | String | Legal name of the store. |
| `phone` | String | Store phone number. |
| `email` | String | Store email address. |
| `timezone` | String | Store timezone. |
| `schema` | String | Store schema, ie the store network subdomain. |
| `get_meta_title` | String | Store SEO meta title. |
| `get_meta_description` | String | Store SEO meta description. |
### storefront\_geos [#storefront_geos]
Returns a list of configured markets, see [geos](#geo).
```jinja title="Example Storefront Geo Switcher"
{% if storefront_geos and storefront_geos|length > 1 %}
{% endif %}
```
### subscription\_terms\_and\_conditions [#subscription_terms_and_conditions]
Content from store subscription terms and conditions settings, typically used in a "Subscription Terms & Conditions" page to automatically pull content in from settings.
```jinja title="subscription_terms_and_conditions"
{{ subscription_terms_and_conditions }}
```
### terms\_and\_conditions [#terms_and_conditions]
Content from store terms and conditions settings, typically used in a "Terms & Conditions" page to automatically pull content in from settings.
```jinja title="terms_and_conditions"
{{ terms_and_conditions }}
```
## Objects [#objects]
Object have many properties that can be accessed in templates.
### address [#address]
| Property | Type | Description |
| ---------- | ------ | ----------------- |
| `line_1` | String | Address line 1. |
| `line_2` | String | Address line 2. |
| `city` | String | Address City. |
| `state` | String | Address State. |
| `postcode` | String | Address Postcode. |
| `country` | String | Address Country. |
### branding [#branding]
Store branding properties accessed through the [store](#store) object to leverage within templates. Branding values are configured in the dashboard at **Settings > Branding**.
| Property | Type | Description |
| --------------- | ------ | -------------------------------------------------------- |
| `logo` | File | Store branding logo, use `.url` to access the file link. |
| `icon` | File | Store branding icon, use `.url` to access the file link. |
| `primary_color` | String | Store branding primary color, returns a HEX code. |
| `accent_color` | String | Store branding accent color, returns a HEX code. |
### currency [#currency]
Currency object accessed through [currencies](#currencies).
| Property | Type | Description |
| -------- | ------ | ----------------------------------- |
| `code` | String | Name of the currency, ie `USD`. |
| `symbol` | String | The symbol of the currency, ie `$`. |
### country [#country]
Country object to access properties about a country, see [storefront\_geos](#storefront_geos) for example usage.
| Property | Type | Description |
| -------- | ------ | ------------------------------------------------------------------------------------------------- |
| `code` | String | Two letter [ISO 3166](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) country code. |
| `name` | String | Full name of the country. |
### geo [#geo]
A `geo` is a combination of a language and currency typically associated with a market, see full example in [storefront\_geos](#storefront_geos).
| Property | Type | Description |
| ---------- | ------ | ------------------------------------------------------------------------------------------------- |
| `currency` | object | The currency object, see [currency](#currency). |
| `country` | object | The country object, see [country](#country) |
| `language` | String | Two letter [ISO 639](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes) language code. |
### image [#image]
Product images, see example usage below.
```jinja title="image"
{% with all_images=product.get_all_images %}
{% for image in all_images %}{% image_thumbnail image.original "100x100" crop="center" as thumb %}
{% endfor %}
{% endif %}
{% endwith %}
```
| Property | Type | Description |
| ---------- | ------ | ------------------------------------------------------------------ |
| `original` | File | The original image file, typically used when creating a thumbnail. |
| `url` | String | The full CDN link to render the image. |
### items (menu) [#items-menu]
A menu `item` has properties to support creating dynamic menus configured through the dashboard menu editor.
```jinja title="Example Dynamic Menu"
{% for item in menus.header_menu.items %}
{% if item.level > 0 %}
{% endif %}
{% endfor %}
```
> **Tip:** Storefront Menus can be up to 3 levels, ensure your custom menu supports 2 nested menu item levels, see child and grandchild above.
| Property | Type | Description |
| --------------- | ------- | ----------------------------------------------------------------------------------- |
| `active` | Boolean | Indicates whether the link is currently active. |
| `child_active` | Boolean | Indicates whether any child link of the current link is active. |
| `child_current` | Boolean | Indicates whether the URL path matches the URL of a child link of the current link. |
| `current` | Boolean | Indicates whether the current URL path matches the URL of the link. |
| `items` | List | Contains the child items belonging to the current menu item. |
| `level` | Integer | Specifies the hierarchical level of the current menu item. |
| `name` | String | Represents the display name of the current menu item. |
| `url` | String | Denotes the URL path for the menu item's href link. |
### page [#page]
Storefront Page object details available in the `pages/page.html` template and custom page templates.
| Property | Type | Description |
| ---------------------- | ------ | -------------------------- |
| `title` | String | Page title. |
| `content` | String | Page content. |
| `get_meta_title` | String | Page SEO meta title. |
| `get_meta_description` | String | Page SEO meta description. |
### paginator [#paginator]
The `paginator` object is available on "list views" where the items to display are paginated from the backend, works in tandem with [page\_obj](#page_obj).
```jinja title="paginator"
{% if paginator.num_pages > 1 %}
{% endif %}
```
| Property | Type | Description |
| ----------- | ------- | ---------------------------------- |
| `num_pages` | Integer | Number of pages in pagination set. |
### page\_obj [#page_obj]
The `page_obj` object is available on "list views" where the items to display are paginated from the backend, works in tandem with [paginator](#paginator).
| Property | Type | Description |
| ---------------------- | ------- | --------------------- |
| `number` | Integer | Current page number. |
| `has_next` | Object | Next page object. |
| `has_previous` | Object | Previous page. |
| `next_page_number` | Integer | Next page number. |
| `previous_page_number` | Integer | Previous page number. |
### post [#post]
Blog post properties available through global [post](#posts) context and the `blog/post.html` and `blog/index.html` templates.
| Property | Type | Description |
| ---------------------- | ------ | ----------------------------------------------------------------------------------------------------------------- |
| `id` | String | The post ID. |
| `featured_image` | File | Blog post featured image file, use `.url` to access full file link. |
| `categories` | List | List of related post categories, use `.all` to return a list of categories, see [post\_category](#post_category). |
| `get_absolute_url` | String | A full path link to the blog post. |
| `title` | String | The post title. |
| `content` | String | Post content. |
| `slug` | String | Post url slug. |
| `get_meta_title` | String | Post SEO meta title. |
| `get_meta_description` | String | Post SEO meta description. |
### post\_category [#post_category]
Blog post category properties available through global [post\_categories](#post_categories) context and the `blog/post.html` and `blog/index.html` templates.
| Property | Type | Description |
| ------------------ | ------ | -------------------------------------- |
| `id` | String | Blog post category ID. |
| `name` | String | Blog post category name. |
| `get_absolute_url` | String | Blog post category canonical url link. |
### product [#product]
Product configured in the store catalogue.
| Property | Type | Description |
| ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------ |
| `id` | String | Product ID. |
| `title` | String | Product title. |
| `get_title` | String | Product title. |
| `get_all_images` | List | List of product images, see [image](#image). |
| `get_description` | String | Product description. |
| `sku` | String | Product stock keeping unit (sku). |
| `categories` | List | List of product categories, use `.all` to return a list of categories, see [product\_category](#product_category). |
| `parent` | Object | Parent product if product is variant (child). |
| `is_child` | Boolean | Product structure indicating this is a variant product. |
| `primary_image` | File | Primary image of the product, use `.url` to access a full file link. |
| `get_absolute_url` | String | Product canonical url link. |
| `num_approved_reviews` | Integer | Count of approved product reviews. |
| `rating` | Integer | Product rating as a number between 1 and 5. |
| `reviews` | Integer | List of product reviews, see [review](#review). |
| `get_meta_title` | String | Product SEO meta title. |
| `get_meta_description` | String | Product SEO meta description. |
### product\_category [#product_category]
Product category object.
| Property | Type | Description |
| ---------------------- | ------ | ------------------------------------------------ |
| `id` | String | Category ID. |
| `name` | String | Category name. |
| `description` | String | Category description. |
| `image` | File | Category image, use `.url` to access image link. |
| `get_absolute_url` | String | Category canonical url link. |
| `get_meta_title` | String | Category SEO meta title. |
| `get_meta_description` | String | Category SEO meta description. |
### price [#price]
Product price object.
| Property | Type | Description |
| -------------- | ------ | --------------------------- |
| `currency` | String | Price currency. |
| `price` | String | Price that will be charged. |
| `price_retail` | String | Suggested retail price. |
### review [#review]
Product review object.
| Property | Type | Description |
| -------- | ------- | ------------------------------------- |
| `id` | String | Review ID. |
| `title` | String | Review title. |
| `score` | Integer | Review score. |
| `user` | Object | The customer that created the review. |
### voucher [#voucher]
Voucher object.
| Property | Type | Description |
| -------- | ------ | -------------- |
| `title` | String | Voucher title. |
| `code` | String | Voucher code. |
## View-Specific Objects [#view-specific-objects]
View-specific objects are available in the templates rendered by their corresponding views. See [Template Contexts](#template-contexts) below for which objects are available in each template.
### session [#session]
The session object is returned by the [`purchase_info_for_product`](https://developers.nextcommerce.com/docs/storefront/themes/templates/tags#purchase_info_for_product) and [`purchase_info_for_line`](https://developers.nextcommerce.com/docs/storefront/themes/templates/tags#purchase_info_for_line) template tags. It contains pricing and availability information for a product in the current user's currency.
```jinja title="Example Product Price with Session"
{% purchase_info_for_product request product as session %}
{% if session.price.exists %}
{% if session.price.price_retail %}
{{ session.price.price_retail|currency:session.price.currency }}
{% endif %}
{{ session.price.price|currency:session.price.currency }}
{% endif %}
{% if not session.availability.is_available_to_buy %}
Out of Stock
{% endif %}
```
**session.price**
| Property | Type | Description |
| -------------- | ------- | ---------------------------------------- |
| `exists` | Boolean | Whether a price exists for this product. |
| `price` | Decimal | The current selling price. |
| `price_retail` | Decimal | The retail/compare-at price, if set. |
| `currency` | String | The currency code for this price. |
| `excl_tax` | Decimal | The price excluding tax. |
**session.availability**
| Property | Type | Description |
| --------------------- | ------- | ------------------------------------- |
| `is_available_to_buy` | Boolean | Whether the product can be purchased. |
### variant\_form [#variant_form]
The variant selection form object available on product detail pages (`catalogue/product.html`). Used to render variant attribute selectors (size, color, etc.) for products with variants.
```jinja title="Example Variant Selection"
{% if variant_form %}
{% for field in variant_form %}
{% render_field field class+="form-select" %}
{% endfor %}
{% endif %}
```
### filters [#filters]
The `filters` object is a list of product filter/facet objects available on category pages (`catalogue/category.html`). Filters allow customers to narrow product listings by attributes like price, color, size, etc. The `has_active_filter` boolean indicates whether any filter is currently applied.
There are three filter types: `price_range`, `boolean`, and `list`. Each type has different properties for rendering the appropriate UI.
```jinja title="Example Category Filters"
{% if filters %}
{% for filter in filters %}
{{ filter.label }}
{% if filter.type == 'price_range' %}
{% elif filter.type == 'boolean' %}
{% else %}
{% for value in filter.values %}
{% endfor %}
{% endif %}
{% endfor %}
{% if has_active_filter %}
{% for filter in filters %}
{% for active in filter.active_values %}
Remove {{ active }}
{% endfor %}
{% endfor %}
{% endif %}
{% endif %}
```
**Common filter properties:**
| Property | Type | Description |
| --------------- | ------ | ------------------------------------------------------- |
| `type` | String | Filter type: `'price_range'`, `'boolean'`, or `'list'`. |
| `label` | String | Display label for the filter. |
| `active_values` | List | List of currently selected filter values. |
| `url_to_remove` | String | URL to remove this active filter. |
**Price range filter properties:**
| Property | Type | Description |
| ---------------------- | ------- | ------------------------------------- |
| `min_value.value` | Decimal | Current minimum price value. |
| `min_value.param_name` | String | Query parameter name for the minimum. |
| `min_value.label` | String | Display label for the minimum input. |
| `max_value.value` | Decimal | Current maximum price value. |
| `max_value.param_name` | String | Query parameter name for the maximum. |
| `max_value.label` | String | Display label for the maximum input. |
| `range_max` | Decimal | Maximum possible range value. |
**Boolean filter properties:**
| Property | Type | Description |
| ------------------------ | ------- | ----------------------------------------- |
| `true_value.param_name` | String | Query parameter name for true selection. |
| `true_value.active` | Boolean | Whether true is currently selected. |
| `true_value.count` | Integer | Number of results matching true. |
| `false_value.param_name` | String | Query parameter name for false selection. |
| `false_value.active` | Boolean | Whether false is currently selected. |
| `false_value.count` | Integer | Number of results matching false. |
**List filter value properties:**
| Property | Type | Description |
| ------------ | ------- | ----------------------------------------- |
| `param_name` | String | Query parameter name for this value. |
| `active` | Boolean | Whether this value is currently selected. |
| `count` | Integer | Number of results matching this value. |
| `value` | String | The filter value. |
| `label` | String | Display label for this value. |
### line [#line]
Cart line object available on the cart page (`templates/cart.html`) through the `formset` context. Each form in the formset exposes its cart line as `form.instance`.
```jinja title="Example Cart Line Properties"
{% for form in formset %}
{% with line=form.instance %}
{% for property in line.properties %}
{{ property.key }}: {{ property.value }}
{% endfor %}
{% endwith %}
{% endfor %}
```
| Property | Type | Description |
| ------------ | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `properties` | List | Line item properties captured on the product page, see [Personalized Products](https://developers.nextcommerce.com/docs/storefront/themes/guides/personalized-products). Property names starting with an underscore are excluded. |
**line.properties**
| Property | Type | Description |
| -------- | ------ | --------------------------------------------------------------------------------- |
| `key` | String | The property name, taken from the `properties[]` input on the product page. |
| `value` | String | The value submitted by the customer. |
## Template Contexts [#template-contexts]
All templates receive the [Global Objects](#global-objects) (`store`, `settings`, `currencies`, `languages_active_storefront`, `menus`, `products`, `product_categories`, `posts`, `post_categories`, `privacy_policy`, `terms_and_conditions`, `subscription_terms_and_conditions`, `request`, `storefront_geos`). The table below lists additional view-specific context variables passed to each template.
| Template | View-Specific Context |
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `templates/index.html` | Global objects only. Use the [`where`](https://developers.nextcommerce.com/docs/storefront/themes/templates/tags#where) tag to query products and categories. |
| `templates/cart.html` | `formset` (cart line forms, each `form.instance` is a [line](#line)) |
| `templates/catalogue/product.html` | `product`, `variant_form`, `interval_count_choices` |
| `templates/catalogue/index.html` | `products` (paginated), `paginator`, `page_obj` |
| `templates/catalogue/category.html` | `category`, `products` (paginated), `filters`, `has_active_filter`, `paginator`, `page_obj` |
| `templates/search.html` | `query`, `products` (paginated), `paginator`, `page_obj` |
| `templates/blog/index.html` | `posts` (paginated), `paginator`, `page_obj` |
| `templates/blog/post.html` | `post` |
| `templates/pages/page.html` | `page` |
| `templates/support/index.html` | `categories` |
| `templates/support/category.html` | `category`, `articles` |
| `templates/support/article.html` | `article` |
| `templates/reviews/index.html` | `product`, `reviews` (paginated), `paginator`, `page_obj` |
| `templates/reviews/form.html` | `product`, `form` |
| `templates/reviews/review.html` | `product`, `review` |
> **Tip:** Use the [`purchase_info_for_product`](https://developers.nextcommerce.com/docs/storefront/themes/templates/tags#purchase_info_for_product) tag in any template to get pricing and availability for a product. Use [`cart_form`](https://developers.nextcommerce.com/docs/storefront/themes/templates/tags#cart_form) on product pages to generate add-to-cart forms.
> **Warning:** **Cart and user data must use the [Storefront GraphQL API](https://developers.nextcommerce.com/docs/storefront/graphql).** All storefront pages are fully cached per language and currency combination. Per-user data (cart contents, authentication state, wishlists) rendered in server-side templates would be cached and served to other visitors. Use client-side JavaScript with the GraphQL API for all cart and user interactions.
## Dashboard Cross-Reference [#dashboard-cross-reference]
Some template variables are populated from dashboard settings. Use this reference to understand where data originates when building or debugging templates.
| Template Variable | Dashboard Path | Description |
| ----------------------------------- | ------------------------------- | ------------------------------------------- |
| `store.branding.logo` | Settings > Branding | Store logo image. |
| `store.branding.icon` | Settings > Branding | Store icon/favicon image. |
| `store.branding.primary_color` | Settings > Branding | Primary brand color (HEX). |
| `store.branding.accent_color` | Settings > Branding | Accent brand color (HEX). |
| `store.name`, `store.tagline` | Settings > General | Store name and tagline. |
| `store.legal_name`, `store.address` | Settings > General | Legal details and address. |
| `menus.{menu_key}.items` | Storefront > Navigation | Navigation menu items (up to 3 levels). |
| `privacy_policy` | Settings > Policies | Privacy policy content. |
| `terms_and_conditions` | Settings > Policies | Terms and conditions content. |
| `subscription_terms_and_conditions` | Settings > Policies | Subscription T\&C content. |
| `settings.*` | Storefront > Themes > Customize | Theme settings from `settings_schema.json`. |
# Tag Reference (https://developers.nextcommerce.com/docs/storefront/themes/templates/tags)
Template tags enable theme developers to include and extend templates and blocks, add logical operators, query and filter data, and much more. See all available template tags below.
### app\_asset\_url [#app_asset_url]
The `app_asset_url` tag is used to reference asset files included in app snippets.
```jinja title="app_asset_url"
```
### app\_hook [#app_hook]
The `app_hook` tag specifies a theme storefront location Apps can inject snippets into to extend storefront templates from Apps. Theme developers should ensure their templates include all available `app_hooks` to ensure compatibility with all Apps.
```jinja title="app_hook"
{% app_hook 'global_header' %}
```
**Available `app_hook` locations include:**
### add\_query\_param [#add_query_param]
The `add_query_param` tag appends or updates a query parameter on the current URL. Commonly used for building pagination links and filter URLs while preserving existing query parameters.
```jinja title="add_query_param"
{% add_query_param request 'page' page_obj.next_page_number %}
```
```jinja title="Example Pagination with add_query_param"
{% if paginator.num_pages > 1 %}
{% endif %}
```
| Argument | Description |
| ----------- | --------------------------------------------- |
| request | The current `request` context object. |
| param\_name | The query parameter name to set, eg `'page'`. |
| value | The value to assign to the parameter. |
### annotate\_form\_field [#annotate_form_field]
The `annotate_form_field` tag adds HTML attributes to a form field based on its Django form field properties (required, type, etc.). Useful for adding client-side validation and accessibility attributes.
```jinja title="annotate_form_field"
{% annotate_form_field field %}
{{ field }}
```
### boolean operators [#boolean-operators]
If tags may be used in combination with boolean operators for conditional control flow.
| Operator | Description |
| -------- | ---------------------------- |
| `and` | multiple conditions are true |
| `or` | either condition is true |
| `not` | a condition is not true |
| `in` | contained within |
| `not in` | a condition is not true |
| `is` | two values are the same |
| `is not` | two values are not the same |
| `==` | equality |
| `!=` | inequality |
| `<` | less than |
| `>` | greater than |
| `<=` | less than or equal to |
| `>=` | greater than or equal to |
### cart\_form [#cart_form]
The `cart_form` tag generates an add-to-cart form for a product. Required on every product page to enable purchasing.
```jinja title="cart_form"
{% cart_form request product 'single' as cart_form %}
```
The tag returns a form object, not rendered HTML. Loop over it to render each field in your own markup, as the Intro Bootstrap theme does through its `partials/form_fields.html` partial.
```jinja title="templates/catalogue/product.html"
{% block product_cart_form %}
{% purchase_info_for_product request product as session %}
{% if session.availability.is_available_to_buy %}
{% cart_form request product 'single' as cart_form %}
{% else %}
{% t "store.catalogue.out_of_stock" %}
{% endif %}
{% endblock %}
```
```jinja title="partials/form_fields.html"
{% if form.is_bound and not form.is_valid %}
{% t "global.error.please_check_error" %}
{% endif %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
{{ error }}
{% endfor %}
{% endif %}
{% for field in form %}
{% include 'partials/form_field.html' with field=field style=style %}
{% endfor %}
```
| Argument | Description |
| -------------- | --------------------------------------------- |
| request | The current `request` context object. |
| product | The `product` context object. |
| quantity\_type | Accepts `'single'` or `'multiple'`. |
| variable | Assigned template variable name for the form. |
Add [line item property](https://developers.nextcommerce.com/docs/storefront/themes/guides/personalized-products) inputs to this form to capture customer personalization such as an engraving or gift message.
### comment [#comment]
Ignores everything between `{% comment %}` and `{% endcomment %}`. An optional note may be inserted in the first tag. For example, this is useful when commenting out code for documenting why the code was disabled.
```jinja title="comment"
Rendered text with {{ pub_date|date:"c" }}
{% comment "Optional note" %}
Commented out text with {{ create_date|date:"c" }}
{% endcomment %}
```
### core\_js [#core_js]
The `core_js` tag outputs the platform's core JavaScript bundle. This is required in every theme's base layout and powers cart functionality, AJAX form submissions, CSRF token handling, and other platform features.
```jinja title="core_js"
{% core_js %}
```
```jinja title="Example Placement in Base Layout"
{# jQuery must be loaded before core_js #}
{% core_js %}