# Develop a Private Commerce App

A private Commerce App is a standard Commerce App Package (CAP) installed with `AppSource=WebDAV`. The platform doesn't require a registry listing. Develop locally, upload with `b2c cap install`, and test on the storefront without publishing.

Build, package, and test using the shared guide. This page covers only the SI distribution path: install from WebDAV, skip the registry, and hand the CAP to the merchant.

## When to Stay Private

Stay private when the app is merchant-specific and shouldn't appear in the Cart & Checkout Hub catalog in Business Manager.

- Use the same CAP format and install job as public apps. See [Architecture Overview](/docs/commerce/b2c-commerce/guide/architecture.md) and [Packaging Your Commerce App](/docs/commerce/b2c-commerce/guide/packaging.md).
- Do not submit the app to the [Commerce App Registry](https://github.com/SalesforceCommerceCloud/commerce-apps). Registry review and `catalog.json` do not apply.
- Install with the B2C CLI or the install job (`app_source: WebDAV`). The app isn't discoverable or click-to-install in the Cart & Checkout Hub catalog. After installation, it appears with its installed state and configuration tasks in Business Manager.

If you later want merchants to find and install the app from Business Manager, follow [Publish to the App Registry](/docs/commerce/b2c-commerce/guide/submission-review.md) instead.

## Prerequisites

- A Commerce Cloud sandbox with Storefront Next enabled
- The [B2C CLI](/docs/commerce/b2c-commerce/guide/development-environment.md) installed, with job execution and WebDAV access
- The instance-level `CommerceAppsEnabled` toggle on (same as ISV installs)

You do **not** need access to the Commerce App Registry repository.

## Local Development Loop

```mermaid
flowchart LR
    A[Local CAP] --> B[validate / package]
    B --> C[WebDAV upload]
    C --> D["InstallCommerceApp CUSTOM_APP"]
    D --> E[BM tasks]
    E --> F[Storefront E2E]
```

1. Scaffold and implement the app. See [Building Your Commerce App](/docs/commerce/b2c-commerce/guide/building-your-app.md).

2. Validate and, when you need an artifact, package:

   ```bash
   b2c cap validate ./my-commerce-app
   b2c cap package ./my-commerce-app --output ./dist
   ```

   See [Packaging Your Commerce App](/docs/commerce/b2c-commerce/guide/packaging.md).

3. Install on the sandbox. Given a directory, the CLI packages, uploads via WebDAV, and starts the install job with `app_source: WebDAV`:

   ```bash
   b2c cap install ./my-commerce-app --site-id RefArch
   ```

4. Complete Business Manager configuration:

   ```bash
   b2c cap tasks my-commerce-app --site-id RefArch
   ```

5. Exercise the shopper flow on Storefront Next. See [Testing and Validation](/docs/commerce/b2c-commerce/guide/testing-validation.md).

6. Inspect, uninstall, and reinstall as you iterate:

   ```bash
   b2c cap list --site-id RefArch
   b2c cap uninstall my-commerce-app --site-id RefArch
   ```

> **Tip:** During rapid development, install from the source directory and skip the separate package step. See [Development Environment Setup](/docs/commerce/b2c-commerce/guide/development-environment.md#inner-development-loop-test-stage).

For all flags, authentication, and OCAPI setup, see [Development Environment Setup](/docs/commerce/b2c-commerce/guide/development-environment.md#cli-commands).

## What Install Does for Private Apps

The install job is the same `sfcc-install-commerce-app` pipeline used for public apps, with these WebDAV differences:

| Behavior                 | Private (`AppSource=WebDAV`)                                                                                                                                                                                                       |
| :----------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Per-app registry listing | Skipped. Unregistered apps install.                                                                                                                                                                                                |
| Domain                   | The job's `app_domain` must still resolve to a recognized registry domain. An unknown domain stops installation before state is created.                                                                                           |
| Feature type             | Forced to `CUSTOM_APP`.                                                                                                                                                                                                            |
| Feature source           | Persisted as `WebDAV`.                                                                                                                                                                                                             |
| Package fetch            | `AppPath` on WebDAV is required.                                                                                                                                                                                                   |
| Display name             | When valid, CAP `commerce-app.json` `name` is stored as optional display metadata.                                                                                                                                                 |
| Icon                     | One top-level SVG or PNG from CAP `icons/` can be stored as optional display metadata when it is within the platform size limit.                                                                                                   |
| Cartridges, IMPEX, state | Same as public installs: unzip, validate `tasksList.json` / optional `adminComponents.json`, copy cartridges, update paths, process install IMPEX (`SITEID` / `LIBRARYID`), persist uninstall IMPEX, write `CommerceFeatureState`. |

Optional storefront PR creation uses the job parameter `should_create_pr` (default `false`). When requested and the CAP contains Storefront Next extensions or cartridges, the job attempts to open a PR against the merchant's Storefront Next repository. With the B2C CLI, add `--create-pr` to `b2c cap install` (see [B2C CLI CAP documentation](https://salesforcecommercecloud.github.io/b2c-developer-tooling/cli/cap.html#creating-a-storefront-pull-request)). If PR creation fails, installation continues and adds a warning task. See [Install Job Parameters](/docs/commerce/b2c-commerce/guide/reference.md#install-job-parameters).

When calling the job API directly, first upload the CAP to WebDAV and set `app_path` to that uploaded file. The CLI normally uploads to `Impex/commerce-apps/`. See the full example in [Reference](/docs/commerce/b2c-commerce/guide/reference.md#install-job-parameters):

```json
POST /s/-/dw/data/v25_6/jobs/sfcc-install-commerce-app/executions
{
  "app_name": "avalara-tax",
  "app_source": "WebDAV",
  "app_domain": "tax",
  "site_id": "Sites-RefArch",
  "app_path": "webdav/Sites/Impex/commerce-apps/avalara-tax-v0.2.5.zip"
}
```

## Constraints

- **Known domain only.** The install job's `app_domain` parameter must match a recognized registry domain (`tax`, `oms`, `shipping`, and the others listed in [Supported Domains](/docs/commerce/b2c-commerce/guide/supported-domains.md)). `b2c cap install` derives this value from `commerce-app.json`; direct job callers supply it explicitly.
- **Not in the Cart & Checkout Hub catalog.** Merchants cannot discover or click-to-install a private app. Install with `b2c cap install` or upload the CAP to WebDAV before calling the job API with `app_source: WebDAV` and `app_path`.
- **Avoid registry ID collisions.** A registry entry isn't required. However, if `app_name` and `app_domain` match an existing entry, the installer can still apply that entry's required feature toggle and storefront compatibility metadata. Use an app ID that doesn't collide with a registered app.
- **Same CAP format.** Private apps should follow the standard CAP format, including `commerce-app.json`, `tasksList.json`, `SITEID` / `LIBRARYID` placeholders, uninstall IMPEX, and hook naming. See [Packaging Your Commerce App](/docs/commerce/b2c-commerce/guide/packaging.md) and [Known Limitations](/docs/commerce/b2c-commerce/guide/reference.md#known-limitations).

## Handoff to the Merchant

1. Deliver the packaged `.zip` from `b2c cap package` through an access-controlled channel. Provide its SHA-256 digest separately so the merchant can verify integrity before installation.
2. The merchant or SI installs on staging with `b2c cap install` or the job API.
3. Promote each app artifact and supported configuration from staging to production, then verify the target state. See [Post-Install Maintenance](/docs/commerce/b2c-commerce/guide/post-publication.md).
4. Do not run `/submit-pr` and do not edit `catalog.json`.

## CI

Use the shared pipeline from [CI/CD Pipeline Integration](/docs/commerce/b2c-commerce/guide/development-environment.md#cicd-pipeline-integration), and drop the registry publish step:

1. **On pull request:** `b2c cap validate <path> --json`
2. **On release:** `b2c cap package <path> --output ./dist --json` and keep the `.zip` as the artifact
3. **On promote:** `b2c cap install ./dist/<app>.zip --site-id <site-id> --clean-archive --json` against a dedicated sandbox, then `b2c cap list --site-id <site-id> --json`. Retain the release artifact in your controlled artifact store instead of leaving a private CAP on WebDAV.
