Storefront Next Deployment
A storefront ships as two independent deployments:
| Deployment | Target | Command |
| --- | --- | --- |
| App bundle (SSR server + client assets) | Managed Runtime | pnpm build then pnpm push |
| Base cartridge (Page Designer metadata, notification Custom API) | B2C Commerce instance (WebDAV code version) | pnpm cartridge:deploy |
If Business Manager Storefront Setup created your project, reuse its MRT project, environments, and SLAS client. Guides: deployment, launch.
Build
pnpm build # extension locales + config aggregation, cartridge:generate, react-router build -> build/
pnpm start # preview the production build at http://localhost:3000
pnpm bundlesize # build with bundle size limits enforced
Run pnpm typecheck, pnpm lint, and pnpm test before pushing. Node 24 is required locally and on MRT (runtime.ssrParameters.ssrFunctionNodeVersion: '24.x').
Push to Managed Runtime
push does not build; it fails if build/ is missing.
pnpm build && pnpm push # upload only (not deployed to an env unless a target is set)
pnpm push -- -m "Release 42" -e staging --wait # deploy to an env and wait
| Need | Provide |
| --- | --- |
| Credentials | MRT_API_KEY (or --api-key, --credentials-file, ~/.mobify); MRT_CLOUD_ORIGIN for a non-default MRT origin |
| Project slug | MRT_PROJECT / -p / SFCC_MRT_PROJECT / dw.json mrtProject (set it explicitly; push errors without one) |
| Target env | MRT_TARGET / -e. Required with --wait. Without it the bundle uploads but is not deployed |
Put MRT_PROJECT and MRT_TARGET in .env for local pushes. Store MRT_API_KEY in your shell or CI secret store, not in committed files. Flags and other commands: storefront-next:sfnext-project-setup references/SFNEXT-CLI.md. Inspect without deploying: pnpm sfnext create-bundle -d . -o .bundle.
Bundle history, rolling back to an earlier bundle, and environment management are generic MRT tasks: b2c mrt bundle history|list|deploy, see b2c-cli:b2c-mrt. Live logs: MCP mrt_logs_watch / mrt_logs_watch_poll, or b2c mrt tail-logs. MCP mrt_bundle_push can also push a bundle.
Environment variables on MRT
.env is not uploaded by push. Set runtime config on the MRT environment:
pnpm config:push-env # b2c mrt env var push: reads .env, shows a diff, asks to confirm
b2c mrt env var push -f .env.staging -p my-project -e staging --yes # explicit file, skips prompt
b2c mrt env var set PUBLIC__app__defaultSiteId=MySite -p my-project -e staging
pnpm sfnext config inspect --project my-project --environment staging # see what is applied
push excludes MRT_-prefixed keys by default. Review the file first: PUBLIC__ values are browser-visible, and local-only values should not be pushed. Variable naming and limits: Salesforce's environment variables guide. Rules for what to set: storefront-next:sfnext-configuration.
Cartridge deployment
pnpm cartridge:generate # Page Designer metadata from decorators (also run by pnpm build)
pnpm cartridge:validate # validate generated JSON
pnpm cartridge:deploy # upload cartridges/ to the instance
pnpm cartridge:deploy -- --delete --reload # wipe old files first, then activate the code version
- Deployment is not part of
pnpm pushand is manual by default. - Needs an instance (
-s/--serverorSFCC_SERVER), WebDAV credentials, and either--code-versionor OAuth credentials to discover the active version (--reloadalso needs OAuth with OCAPIcode_versionsaccess). Settings resolve from flags, env, ordw.json; seeb2c-cli:b2c-codefor the shared auth model. - Redeploy whenever Page Designer decorators or attribute definitions change; stale components in Business Manager mean the cartridge is behind.
- The base cartridge also hosts the notification Custom API used by passwordless login, password reset, OTP, and guest order lookup emails. Once per client, register its SLAS scope with
sfnext setup-base-cartridge --slas-client-id <id>(docs/README-EMAIL-CARTRIDGE.md).
CI/CD
The project ships .github/workflows/deploy.yml: on push to the latest branch (or manual dispatch) it builds, runs pnpm push --wait (needs secret MRT_API_KEY, variables MRT_PROJECT, MRT_TARGET), and deploys cartridges with the b2c code-deploy action (needs SFCC_SERVER, SFCC_CLIENT_ID, secret SFCC_CLIENT_SECRET). Each job skips cleanly when its configuration is absent. Read the file before changing branch names or environments.
Pre-launch checklist
pnpm typecheck && pnpm lint && pnpm testpass;pnpm bundlesizewithin limits.- MRT variables set on the target env: your own client ID, organization ID, short code, site(s);
pnpm config:inspectshows no unintended demo values. - Demo analytics IDs/hosts in
app.engagement.adaptersreplaced or disabled. images.hostswitched from the DIS staging host to production;realmHostMappingsfor custom domains.- Cartridge deployed and code version activated; SLAS scopes registered; Page Designer pages publish and render.
- SLAS redirect URIs include every production domain; cookie domain and Business Manager Hybrid Auth level agree if used (
references/MRT-DEPLOYMENT.md). url.seoRouteshas an entry per active site if enabled (protected: needs a rebuild).- Security headers/CSP and Turnstile reviewed (
storefront-next:sfnext-security); robots and sitemap handled (storefront-next:sfnext-seo). - Smoke test after deploy: home, PLP, PDP, cart, login, checkout, and a Page Designer page.
Upgrading a project
Your project records storefrontNext.templateRelease, templateVersion, and minSdkVersion in package.json; docs/COMPATIBILITY.md maps template releases to the SDK (@salesforce/storefront-next-dev / -runtime) versions they need. Follow the step-by-step guides in docs/migrations/ (for example react-router-7.18: pin react-router and every @react-router/* package to exactly 7.18.2, and seo-url-rules). Upgrade SDK packages, run pnpm install, pnpm typecheck, and tests, then redeploy.
Troubleshooting
| Symptom | Cause / fix |
| --- | --- |
| Build directory ... does not exist | Run pnpm build before pnpm push |
| Push: project slug required | Set MRT_PROJECT (or -p) |
| Push: credentials required / 401 | MRT_API_KEY missing or for a different MRT user; check --credentials-file |
| --wait error about environment | Add -e <env> or MRT_TARGET |
| 500 after deploy | Required PUBLIC__ variables missing on that MRT environment; pnpm sfnext config inspect --environment <env>; tail logs (b2c-cli:b2c-mrt) |
| Env var "not applied" on MRT | Key not in config.server.ts (ignored with a warning) or a protected path; see storefront-next:sfnext-configuration |
| Stale Page Designer components | Cartridge not regenerated/deployed or code version not activated |
| Build fails on client chunk importing server config | server-config.ts imported from client code |
Related Skills
storefront-next:sfnext-project-setup- Scripts, CLI reference, first runstorefront-next:sfnext-configuration- Config and env var rules, multi-site/base path/cookie domainstorefront-next:sfnext-page-designer- Decorators and cartridge metadatastorefront-next:sfnext-performance- Bundle size and Lighthousestorefront-next:sfnext-quality-gates- Pre-push lint/type/test gatesb2c-cli:b2c-mrt- MRT projects, environments, bundles, env vars, redirects, logsb2c-cli:b2c-code- Code version and cartridge deploy with the b2c CLI
Finding more
Project docs/README-BASE-PATH.md, README-MULTI-DOMAIN.md, README-COOKIE-DOMAIN.md, README-EMAIL-CARTRIDGE.md, docs/migrations/; b2c docs search "<topic>" --category sfnext.