SFCC Cartridge Development: The Complete Guide for Developers

If you are building on Salesforce Commerce Cloud, you need to understand **cartridges**. Cartridges are the core modular unit of SFCC development — the equivalent of packages or modules in other frameworks. Every piece of custom code, every third-party integration, and every storefront template in SFCC lives in a cartridge.

This guide covers everything a developer needs to know to work effectively with SFCC cartridges.

---

## What Is an SFCC Cartridge?

A cartridge is a self-contained directory that follows a specific file structure and can be activated on one or more SFCC sites. Cartridges contain:

- **Controllers** — server-side JavaScript (SFCC's proprietary server framework) that handles route logic
- **Templates (ISML)** — server-rendered HTML templates using SFCC's ISML templating language
- **Client-side assets** — JavaScript, CSS, and images bundled via webpack (in SFRA)
- **Scripts** — reusable server-side utility scripts
- **Static** — fonts, images, and other static assets
- **Metadata** — system object extensions and custom object definitions
- **Configuration** — cartridge-specific settings and service definitions

---

## The Cartridge Path

The **cartridge path** is the ordered list of cartridges active on a site. When SFCC needs to resolve a resource (a controller, template, or script), it searches cartridges from left to right along the cartridge path and uses the first match it finds.

This is how SFCC implements the **override pattern**:

```
app_custom_storefront:app_storefront_base
```

In this example, when a request comes in for a controller, SFCC checks `app_custom_storefront` first. If the controller exists there, it's used. If not, SFCC falls back to `app_storefront_base`.

This pattern is fundamental to SFCC development. You **never modify** base cartridges (like `app_storefront_base`). Instead, you create a custom cartridge that overrides only the files you need to change.

---

## Storefront Reference Architecture (SFRA)

SFRA is Salesforce's recommended storefront architecture, introduced in 2018 as the replacement for the legacy Site Genesis framework. SFRA is itself delivered as a set of cartridges:

- **app_storefront_base** — the core SFRA cartridge with all controllers, templates, and client-side code
- **modules** — shared SFRA utilities
- **bm_app_storefront_base** — Business Manager extensions for SFRA

For any SFRA project, you create a custom cartridge (e.g., `app_custom_myproject`) that overrides the specific controllers, templates, and scripts you need to customise.

---

## Creating a Custom Cartridge

A minimal SFCC cartridge has this structure:

```
my_cartridge/
cartridge/
controllers/
forms/
models/
scripts/
static/
default/
css/
js/
templates/
default/
package.json
```

The `cartridge/` directory is the root of all cartridge content. The `package.json` at the cartridge root (not inside `cartridge/`) defines the cartridge name used in the cartridge path.

---

## Controllers in SFCC

SFCC controllers are server-side JavaScript files that define the route handlers for your storefront. In SFRA, controllers use the `server` module:

```javascript
'use strict';

var server = require('server');
var page = module.superModule;
server.extend(page);

server.append('Show', function (req, res, next) {
var viewData = res.getViewData();
viewData.customData = 'hello world';
res.setViewData(viewData);
next();
});

module.exports = server.exports();
```

Key concepts:

- **server.extend(page)** — inherit all routes from the parent cartridge's controller
- **server.append** — add logic that runs after the parent route, without replacing it
- **server.replace** — completely replace a parent route
- **server.prepend** — add logic that runs before the parent route

In practice, I use `server.append` for 90% of customisations. It lets you add data to the view model or modify response headers without touching the parent route's core logic, which means base cartridge upgrades are far less painful. I reach for `server.replace` only when the parent route's logic is fundamentally wrong for the use case — for example, when a checkout step needs completely different validation rules or a redirect flow that cannot be layered on top of the existing one.

---

## ISML Templates

ISML (Internet Store Markup Language) is SFCC's server-side templating language. It extends HTML with SFCC-specific tags:

```html
<isscript>
var product = pdict.product;
</isscript>


<isprint value="${product.name}" encoding="html" />


<isif condition="${product.available}">
Add to Cart
<iselse/>
Out of Stock
</isif>
```

Key ISML tags:

- **`<isscript>`** — execute server-side JavaScript
- **`<isprint>`** — output a value (always use `encoding="html"` for user-generated content)
- **`<isif>` / `<iselse>` / `<iselseif>`** — conditional rendering
- **`<isloop>`** — iterate over collections
- **`<isinclude>`** — include another ISML template
- **`<isdecorate>`** — apply a page decorator template

---

## Models and Scripts

In SFRA, **models** are server-side JavaScript classes that transform SFCC API objects into plain data objects suitable for passing to templates. They live in `cartridge/models/`.

**Scripts** are utility functions used by controllers and models. They live in `cartridge/scripts/`.

A clean SFRA architecture separates concerns:
- Controllers handle routing and request/response orchestration
- Models transform and prepare data
- Scripts implement business logic
- Templates render HTML

---

## Cartridge Development Best Practices

The rule that matters most: never touch base cartridges. Not even a small fix, not even a one-liner. The moment you modify `app_storefront_base` directly, you own that file forever. Every Salesforce patch and compatibility release becomes a manual merge exercise. Always create a custom cartridge, always use the override pattern, and keep your changes isolated to what you actually need to change.

Keep your cartridges focused. One cartridge for your custom storefront logic, one per third-party integration (payment gateway, loyalty, search), and nothing else in each. I have inherited projects with monolithic custom cartridges that mixed storefront code, payment logic, and a marketing tag implementation into one 400-file directory. Debugging regressions in that environment is painful. Document every custom system object extension you add in cartridge metadata — they are invisible in Business Manager to anyone who did not build them, and they regularly get missed in handovers.

---

## Debugging SFCC Cartridges

SFCC provides several debugging tools:

- **Log Center in Business Manager** — access custom `dw.system.Logger` output and system error logs
- **Prophet Debugger** (VS Code extension) — the standard SFCC development tool for code upload, step-through debugging, and log streaming
- **Request Logger** — capture and inspect HTTP requests through the SFCC pipeline
- **Pipeline Profiler** — performance profiling for legacy pipeline code

For modern SFRA development, Prophet Debugger is the essential tool. Configure it with your SFCC sandbox credentials to enable real-time code sync and breakpoint debugging. The `dw.json` file sits at the project root and holds your sandbox hostname, code version, and credentials:

```json
{
"hostname": "your-sandbox.demandware.net",
"username": "your-username",
"password": "your-password",
"code-version": "version1"
}
```

One thing that catches people out on Windows: if you are running Prophet on Git Bash, the SSL certificate validation against staging/production sandboxes can fail silently. The extension just stops uploading without an obvious error. The fix is to set `"self-signed": true` in `dw.json` for sandbox environments, or ensure your VS Code is using the system certificate store. I wasted a full afternoon on this during a Barbour staging setup before finding it in the Prophet GitHub issues.

---

## Getting Certified in SFCC Development

If you are serious about SFCC as a career, consider the official Salesforce certifications:

- **B2C Commerce Developer** — the foundational certification for SFCC developers
- **B2C Commerce Architect** — senior-level certification covering solution design and architecture

Both certifications are available through Trailhead and require practical knowledge of cartridge development, Business Manager configuration, and SFCC's API layer. See the [SFCC certification guide](/en/blog/sfcc-certification-guide) for a detailed breakdown of what each exam covers. Understanding how Business Manager interacts with your cartridge code is tested in both — the [Business Manager guide](/en/blog/sfcc-business-manager-guide) covers the operational side in depth.