@salesforce/b2c-cli 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (421) hide show
  1. package/bin/dev.js +8 -8
  2. package/bin/run.js +5 -7
  3. package/content/guidance/b2c/b2c-business-manager-extensions/SKILL.md +361 -0
  4. package/content/guidance/b2c/b2c-business-manager-extensions/references/EXTENSIONS-XML.md +458 -0
  5. package/content/guidance/b2c/b2c-controllers/SKILL.md +301 -0
  6. package/content/guidance/b2c/b2c-controllers/references/CLASSIC-PATTERNS.md +335 -0
  7. package/content/guidance/b2c/b2c-controllers/references/SFRA-PATTERNS.md +400 -0
  8. package/content/guidance/b2c/b2c-custom-api-development/SKILL.md +281 -0
  9. package/content/guidance/b2c/b2c-custom-api-development/references/CONTRACT.md +142 -0
  10. package/content/guidance/b2c/b2c-custom-api-development/references/IMPLEMENTATION.md +153 -0
  11. package/content/guidance/b2c/b2c-custom-api-development/references/TESTING.md +118 -0
  12. package/content/guidance/b2c/b2c-custom-caches/SKILL.md +279 -0
  13. package/content/guidance/b2c/b2c-custom-job-steps/SKILL.md +520 -0
  14. package/content/guidance/b2c/b2c-custom-job-steps/references/CHUNK-ORIENTED.md +377 -0
  15. package/content/guidance/b2c/b2c-custom-job-steps/references/JOBS-XML.md +212 -0
  16. package/content/guidance/b2c/b2c-custom-job-steps/references/STEPTYPES-JSON.md +373 -0
  17. package/content/guidance/b2c/b2c-custom-job-steps/references/TASK-ORIENTED.md +344 -0
  18. package/content/guidance/b2c/b2c-custom-objects/SKILL.md +327 -0
  19. package/content/guidance/b2c/b2c-custom-objects/references/OCAPI-SEARCH.md +298 -0
  20. package/content/guidance/b2c/b2c-forms/SKILL.md +242 -0
  21. package/content/guidance/b2c/b2c-forms/references/FORM-XML.md +409 -0
  22. package/content/guidance/b2c/b2c-hooks/SKILL.md +500 -0
  23. package/content/guidance/b2c/b2c-hooks/references/OCAPI-SCAPI-HOOKS.md +403 -0
  24. package/content/guidance/b2c/b2c-hooks/references/ORDER-HOOK-LIFECYCLE.md +169 -0
  25. package/content/guidance/b2c/b2c-hooks/references/SYSTEM-HOOKS.md +433 -0
  26. package/content/guidance/b2c/b2c-isml/SKILL.md +320 -0
  27. package/content/guidance/b2c/b2c-isml/references/EXPRESSIONS.md +366 -0
  28. package/content/guidance/b2c/b2c-isml/references/TAGS.md +443 -0
  29. package/content/guidance/b2c/b2c-localization/SKILL.md +344 -0
  30. package/content/guidance/b2c/b2c-localization/references/PATTERNS.md +407 -0
  31. package/content/guidance/b2c/b2c-logging/SKILL.md +352 -0
  32. package/content/guidance/b2c/b2c-logging/references/LOG-FILES.md +282 -0
  33. package/content/guidance/b2c/b2c-metadata/SKILL.md +406 -0
  34. package/content/guidance/b2c/b2c-metadata/references/SYSTEM-OBJECTS.md +320 -0
  35. package/content/guidance/b2c/b2c-metadata/references/XML-EXAMPLES.md +366 -0
  36. package/content/guidance/b2c/b2c-onboarding/SKILL.md +154 -0
  37. package/content/guidance/b2c/b2c-ordering/SKILL.md +391 -0
  38. package/content/guidance/b2c/b2c-page-designer/SKILL.md +410 -0
  39. package/content/guidance/b2c/b2c-page-designer/references/ATTRIBUTE-TYPES.md +436 -0
  40. package/content/guidance/b2c/b2c-page-designer/references/META-DEFINITIONS.md +340 -0
  41. package/content/guidance/b2c/b2c-querying-data/SKILL.md +289 -0
  42. package/content/guidance/b2c/b2c-querying-data/references/PERFORMANCE-APIS.md +74 -0
  43. package/content/guidance/b2c/b2c-scapi-admin/SKILL.md +53 -0
  44. package/content/guidance/b2c/b2c-scapi-admin/references/CLIENT-EXAMPLES.md +440 -0
  45. package/content/guidance/b2c/b2c-scapi-admin/references/INTEGRATION-PATTERNS.md +518 -0
  46. package/content/guidance/b2c/b2c-scapi-admin/references/OAUTH-SCOPES.md +337 -0
  47. package/content/guidance/b2c/b2c-scapi-shopper/SKILL.md +56 -0
  48. package/content/guidance/b2c/b2c-scapi-shopper/references/CHECKOUT-FLOW.md +466 -0
  49. package/content/guidance/b2c/b2c-scapi-shopper/references/CLIENT-EXAMPLES.md +351 -0
  50. package/content/guidance/b2c/b2c-scapi-shopper/references/COMMON-PATTERNS.md +390 -0
  51. package/content/guidance/b2c/b2c-scapi-shopper/references/SCOPES.md +290 -0
  52. package/content/guidance/b2c/b2c-slas-auth-patterns/SKILL.md +420 -0
  53. package/content/guidance/b2c/b2c-slas-auth-patterns/references/PASSKEYS.md +126 -0
  54. package/content/guidance/b2c/b2c-slas-auth-patterns/references/SESSION-BRIDGE.md +267 -0
  55. package/content/guidance/b2c/b2c-slas-auth-patterns/references/TOKEN-LIFECYCLE.md +367 -0
  56. package/content/guidance/b2c/b2c-webservices/SKILL.md +318 -0
  57. package/content/guidance/b2c/b2c-webservices/references/FTP-SERVICES.md +524 -0
  58. package/content/guidance/b2c/b2c-webservices/references/HTTP-SERVICES.md +578 -0
  59. package/content/guidance/b2c/b2c-webservices/references/SERVICES-XML.md +351 -0
  60. package/content/guidance/b2c/b2c-webservices/references/SOAP-SERVICES.md +587 -0
  61. package/content/guidance/b2c-cli/b2c-am/SKILL.md +277 -0
  62. package/content/guidance/b2c-cli/b2c-bm-users-roles/SKILL.md +210 -0
  63. package/content/guidance/b2c-cli/b2c-cap/SKILL.md +131 -0
  64. package/content/guidance/b2c-cli/b2c-cip/SKILL.md +116 -0
  65. package/content/guidance/b2c-cli/b2c-cip/references/KNOWN_TABLES.md +105 -0
  66. package/content/guidance/b2c-cli/b2c-cip/references/SALES_ANALYSIS.md +50 -0
  67. package/content/guidance/b2c-cli/b2c-cip/references/STARTER_QUERIES.md +147 -0
  68. package/content/guidance/b2c-cli/b2c-code/SKILL.md +146 -0
  69. package/content/guidance/b2c-cli/b2c-config/SKILL.md +462 -0
  70. package/content/guidance/b2c-cli/b2c-content/SKILL.md +176 -0
  71. package/content/guidance/b2c-cli/b2c-debug/SKILL.md +138 -0
  72. package/content/guidance/b2c-cli/b2c-docs/SKILL.md +301 -0
  73. package/content/guidance/b2c-cli/b2c-ecdn/SKILL.md +135 -0
  74. package/content/guidance/b2c-cli/b2c-ecdn/references/ADVANCED.md +97 -0
  75. package/content/guidance/b2c-cli/b2c-ecdn/references/SECURITY.md +75 -0
  76. package/content/guidance/b2c-cli/b2c-import-set-migrations/SKILL.md +265 -0
  77. package/content/guidance/b2c-cli/b2c-job/SKILL.md +64 -0
  78. package/content/guidance/b2c-cli/b2c-job/references/EXPORT.md +121 -0
  79. package/content/guidance/b2c-cli/b2c-job/references/IMPORT.md +55 -0
  80. package/content/guidance/b2c-cli/b2c-job/references/RUN-AND-MONITOR.md +119 -0
  81. package/content/guidance/b2c-cli/b2c-logs/SKILL.md +249 -0
  82. package/content/guidance/b2c-cli/b2c-metrics/SKILL.md +315 -0
  83. package/content/guidance/b2c-cli/b2c-mrt/SKILL.md +207 -0
  84. package/content/guidance/b2c-cli/b2c-mrt/references/BUNDLE-COMMANDS.md +203 -0
  85. package/content/guidance/b2c-cli/b2c-mrt/references/ENVIRONMENT-COMMANDS.md +218 -0
  86. package/content/guidance/b2c-cli/b2c-mrt/references/PROJECT-COMMANDS.md +154 -0
  87. package/content/guidance/b2c-cli/b2c-sandbox/SKILL.md +112 -0
  88. package/content/guidance/b2c-cli/b2c-scapi-custom/SKILL.md +126 -0
  89. package/content/guidance/b2c-cli/b2c-scapi-schemas/SKILL.md +66 -0
  90. package/content/guidance/b2c-cli/b2c-scapi-schemas/references/CLI-EXAMPLES.md +108 -0
  91. package/content/guidance/b2c-cli/b2c-site-import-export/SKILL.md +57 -0
  92. package/content/guidance/b2c-cli/b2c-site-import-export/references/IMPORT-OPTIONS.md +118 -0
  93. package/content/guidance/b2c-cli/b2c-site-import-export/references/METADATA-XML.md +381 -0
  94. package/content/guidance/b2c-cli/b2c-site-import-export/references/WORKFLOWS.md +182 -0
  95. package/content/guidance/b2c-cli/b2c-sites/SKILL.md +112 -0
  96. package/content/guidance/b2c-cli/b2c-slas/SKILL.md +182 -0
  97. package/content/guidance/b2c-cli/b2c-webdav/SKILL.md +186 -0
  98. package/content/guidance/b2c-ops/b2c-checkout-triage/SKILL.md +68 -0
  99. package/content/guidance/b2c-ops/b2c-job-health/SKILL.md +75 -0
  100. package/content/guidance/b2c-ops/b2c-job-health/references/job-logs.md +21 -0
  101. package/content/guidance/b2c-ops/b2c-order-failure-triage/SKILL.md +66 -0
  102. package/content/guidance/b2c-ops/b2c-order-failure-triage/references/order-evidence.md +87 -0
  103. package/content/guidance/b2c-ops/b2c-production-triage/SKILL.md +87 -0
  104. package/content/guidance/b2c-ops/b2c-production-triage/references/escalation.md +57 -0
  105. package/content/guidance/index.json +1949 -0
  106. package/content/guidance/storefront-next/sfnext-accessibility/SKILL.md +103 -0
  107. package/content/guidance/storefront-next/sfnext-accessibility/references/checklist.md +64 -0
  108. package/content/guidance/storefront-next/sfnext-analytics-consent/SKILL.md +91 -0
  109. package/content/guidance/storefront-next/sfnext-analytics-consent/references/CUSTOM-ADAPTER.md +49 -0
  110. package/content/guidance/storefront-next/sfnext-authentication/SKILL.md +127 -0
  111. package/content/guidance/storefront-next/sfnext-authentication/references/COOKIES.md +39 -0
  112. package/content/guidance/storefront-next/sfnext-authentication/references/LOGIN-FLOWS.md +59 -0
  113. package/content/guidance/storefront-next/sfnext-commerce-features/SKILL.md +67 -0
  114. package/content/guidance/storefront-next/sfnext-commerce-features/references/FEATURE-PREREQUISITES.md +37 -0
  115. package/content/guidance/storefront-next/sfnext-components/SKILL.md +153 -0
  116. package/content/guidance/storefront-next/sfnext-components/references/COMPONENT-AUTHORING.md +118 -0
  117. package/content/guidance/storefront-next/sfnext-components/references/SHAPE-TOKENS.md +51 -0
  118. package/content/guidance/storefront-next/sfnext-components/references/STORYBOOK.md +54 -0
  119. package/content/guidance/storefront-next/sfnext-components/references/TOKEN-SYSTEM.md +53 -0
  120. package/content/guidance/storefront-next/sfnext-components/references/TROUBLESHOOTING.md +19 -0
  121. package/content/guidance/storefront-next/sfnext-configuration/SKILL.md +163 -0
  122. package/content/guidance/storefront-next/sfnext-configuration/references/ENV-VARIABLES.md +55 -0
  123. package/content/guidance/storefront-next/sfnext-configuration/references/MULTI-SITE-URLS.md +137 -0
  124. package/content/guidance/storefront-next/sfnext-data-fetching/SKILL.md +140 -0
  125. package/content/guidance/storefront-next/sfnext-data-fetching/references/ACTIONS.md +53 -0
  126. package/content/guidance/storefront-next/sfnext-data-fetching/references/API-CLIENTS.md +34 -0
  127. package/content/guidance/storefront-next/sfnext-data-fetching/references/LOADERS.md +73 -0
  128. package/content/guidance/storefront-next/sfnext-data-fetching/references/SCAPI-FETCHER.md +39 -0
  129. package/content/guidance/storefront-next/sfnext-deployment/SKILL.md +127 -0
  130. package/content/guidance/storefront-next/sfnext-deployment/references/MRT-DEPLOYMENT.md +59 -0
  131. package/content/guidance/storefront-next/sfnext-extensions/SKILL.md +118 -0
  132. package/content/guidance/storefront-next/sfnext-extensions/references/ACTION-HOOKS.md +57 -0
  133. package/content/guidance/storefront-next/sfnext-extensions/references/BASE-AUDIT.md +68 -0
  134. package/content/guidance/storefront-next/sfnext-extensions/references/CLI-AND-INSTALL.md +58 -0
  135. package/content/guidance/storefront-next/sfnext-extensions/references/EXTENSION-EXAMPLES.md +79 -0
  136. package/content/guidance/storefront-next/sfnext-hybrid-storefronts/SKILL.md +93 -0
  137. package/content/guidance/storefront-next/sfnext-hybrid-storefronts/references/HYBRID-PROXY-CONFIG.md +86 -0
  138. package/content/guidance/storefront-next/sfnext-i18n/SKILL.md +152 -0
  139. package/content/guidance/storefront-next/sfnext-i18n/references/locale-config.md +35 -0
  140. package/content/guidance/storefront-next/sfnext-overview/SKILL.md +101 -0
  141. package/content/guidance/storefront-next/sfnext-page-designer/SKILL.md +202 -0
  142. package/content/guidance/storefront-next/sfnext-page-designer/references/BUSINESS-MANAGER.md +46 -0
  143. package/content/guidance/storefront-next/sfnext-page-designer/references/COMPONENT-REGISTRY.md +111 -0
  144. package/content/guidance/storefront-next/sfnext-page-designer/references/DECORATOR-PATTERNS.md +168 -0
  145. package/content/guidance/storefront-next/sfnext-page-designer/references/REVIEW-CHECKLIST.md +83 -0
  146. package/content/guidance/storefront-next/sfnext-page-designer/references/TROUBLESHOOTING.md +35 -0
  147. package/content/guidance/storefront-next/sfnext-performance/SKILL.md +102 -0
  148. package/content/guidance/storefront-next/sfnext-performance/references/PERFORMANCE-REVIEW-CHECKLIST.md +85 -0
  149. package/content/guidance/storefront-next/sfnext-performance/references/SUSPENSE-AND-STREAMING.md +58 -0
  150. package/content/guidance/storefront-next/sfnext-project-setup/SKILL.md +147 -0
  151. package/content/guidance/storefront-next/sfnext-project-setup/references/PROJECT-STRUCTURE.md +61 -0
  152. package/content/guidance/storefront-next/sfnext-project-setup/references/SCRIPTS.md +47 -0
  153. package/content/guidance/storefront-next/sfnext-project-setup/references/SFNEXT-CLI.md +63 -0
  154. package/content/guidance/storefront-next/sfnext-quality-gates/SKILL.md +70 -0
  155. package/content/guidance/storefront-next/sfnext-quality-gates/references/lint-and-budgets.md +39 -0
  156. package/content/guidance/storefront-next/sfnext-revalidation/SKILL.md +121 -0
  157. package/content/guidance/storefront-next/sfnext-revalidation/references/POLICIES-AND-TAGS.md +55 -0
  158. package/content/guidance/storefront-next/sfnext-routing/SKILL.md +123 -0
  159. package/content/guidance/storefront-next/sfnext-routing/references/ROUTE-CONVENTIONS.md +65 -0
  160. package/content/guidance/storefront-next/sfnext-routing/references/URLS-AND-SEO-ROUTES.md +22 -0
  161. package/content/guidance/storefront-next/sfnext-scapi/SKILL.md +126 -0
  162. package/content/guidance/storefront-next/sfnext-scapi/references/WORKED-EXAMPLE.md +39 -0
  163. package/content/guidance/storefront-next/sfnext-security/SKILL.md +129 -0
  164. package/content/guidance/storefront-next/sfnext-security/references/COOKIE-DOMAIN.md +39 -0
  165. package/content/guidance/storefront-next/sfnext-security/references/TURNSTILE.md +43 -0
  166. package/content/guidance/storefront-next/sfnext-seo/SKILL.md +95 -0
  167. package/content/guidance/storefront-next/sfnext-seo/references/MULTI-DOMAIN-BASE-PATH.md +17 -0
  168. package/content/guidance/storefront-next/sfnext-seo/references/SEO-ROUTES.md +31 -0
  169. package/content/guidance/storefront-next/sfnext-state-management/SKILL.md +114 -0
  170. package/content/guidance/storefront-next/sfnext-state-management/references/PATTERNS.md +45 -0
  171. package/content/guidance/storefront-next/sfnext-testing/SKILL.md +151 -0
  172. package/content/guidance/storefront-next/sfnext-testing/references/E2E.md +38 -0
  173. package/content/guidance/storefront-next/sfnext-testing/references/STORYBOOK-PATTERNS.md +97 -0
  174. package/content/guidance/storefront-next/sfnext-testing/references/UNIT-AND-ROUTE-TESTS.md +60 -0
  175. package/content/guidance/storefront-next/sfnext-theming/SKILL.md +104 -0
  176. package/content/guidance/storefront-next/sfnext-theming/references/REBRAND-CHECKLIST.md +29 -0
  177. package/dist/commands/cap/install.d.ts +1 -0
  178. package/dist/commands/cap/list.d.ts +1 -0
  179. package/dist/commands/cap/pull.d.ts +1 -0
  180. package/dist/commands/cap/tasks.d.ts +1 -0
  181. package/dist/commands/cap/uninstall.d.ts +1 -0
  182. package/dist/commands/cip/describe.d.ts +1 -0
  183. package/dist/commands/cip/query.d.ts +1 -0
  184. package/dist/commands/cip/report/bot-traffic-share.d.ts +1 -0
  185. package/dist/commands/cip/report/checkout-funnel-dropoff.d.ts +1 -0
  186. package/dist/commands/cip/report/controller-error-rate-trend.d.ts +1 -0
  187. package/dist/commands/cip/report/controller-health-scorecard.d.ts +1 -0
  188. package/dist/commands/cip/report/customer-registration-trends.d.ts +1 -0
  189. package/dist/commands/cip/report/discount-depth-breakdown.d.ts +1 -0
  190. package/dist/commands/cip/report/inventory-stockout-by-location.d.ts +1 -0
  191. package/dist/commands/cip/report/new-vs-returning-buyer-revenue.d.ts +1 -0
  192. package/dist/commands/cip/report/ocapi-client-usage.d.ts +1 -0
  193. package/dist/commands/cip/report/ocapi-requests.d.ts +1 -0
  194. package/dist/commands/cip/report/payment-method-performance.d.ts +1 -0
  195. package/dist/commands/cip/report/product-co-purchase-analysis.d.ts +1 -0
  196. package/dist/commands/cip/report/promotion-discount-analysis.d.ts +1 -0
  197. package/dist/commands/cip/report/promotion-roi-leaderboard.d.ts +1 -0
  198. package/dist/commands/cip/report/recommender-effectiveness.d.ts +1 -0
  199. package/dist/commands/cip/report/remote-include-performance.d.ts +1 -0
  200. package/dist/commands/cip/report/revenue-by-channel.d.ts +1 -0
  201. package/dist/commands/cip/report/sales-analytics.d.ts +1 -0
  202. package/dist/commands/cip/report/sales-summary.d.ts +1 -0
  203. package/dist/commands/cip/report/scapi-cache-hit-ratio.d.ts +1 -0
  204. package/dist/commands/cip/report/scapi-error-rate-by-status.d.ts +1 -0
  205. package/dist/commands/cip/report/scapi-latency-distribution.d.ts +1 -0
  206. package/dist/commands/cip/report/scapi-traffic-latency.d.ts +1 -0
  207. package/dist/commands/cip/report/search-query-performance.d.ts +1 -0
  208. package/dist/commands/cip/report/top-referrers.d.ts +1 -0
  209. package/dist/commands/cip/report/top-selling-products.d.ts +1 -0
  210. package/dist/commands/cip/report/zero-result-searches.d.ts +1 -0
  211. package/dist/commands/cip/tables.d.ts +1 -0
  212. package/dist/commands/code/activate.d.ts +1 -0
  213. package/dist/commands/code/delete.d.ts +1 -0
  214. package/dist/commands/code/deploy.d.ts +1 -0
  215. package/dist/commands/code/download.d.ts +1 -0
  216. package/dist/commands/code/watch.d.ts +1 -0
  217. package/dist/commands/commands/search.d.ts +35 -0
  218. package/dist/commands/commands/search.js +85 -0
  219. package/dist/commands/commands/search.js.map +1 -0
  220. package/dist/commands/content/export.d.ts +1 -0
  221. package/dist/commands/content/list.d.ts +1 -0
  222. package/dist/commands/content/validate.d.ts +1 -0
  223. package/dist/commands/debug/cli.d.ts +1 -0
  224. package/dist/commands/debug/index.d.ts +1 -0
  225. package/dist/commands/docs/cache.d.ts +1 -0
  226. package/dist/commands/docs/download.d.ts +1 -0
  227. package/dist/commands/docs/read.d.ts +1 -0
  228. package/dist/commands/docs/schema.d.ts +1 -0
  229. package/dist/commands/docs/search.d.ts +1 -0
  230. package/dist/commands/docs/skill.d.ts +41 -0
  231. package/dist/commands/docs/skill.js +183 -0
  232. package/dist/commands/docs/skill.js.map +1 -0
  233. package/dist/commands/ecdn/cache/purge.d.ts +1 -0
  234. package/dist/commands/ecdn/certificates/add.d.ts +1 -0
  235. package/dist/commands/ecdn/certificates/delete.d.ts +1 -0
  236. package/dist/commands/ecdn/certificates/list.d.ts +1 -0
  237. package/dist/commands/ecdn/certificates/update.d.ts +1 -0
  238. package/dist/commands/ecdn/certificates/validate.d.ts +1 -0
  239. package/dist/commands/ecdn/cipher-suites/get.d.ts +1 -0
  240. package/dist/commands/ecdn/cipher-suites/update.d.ts +1 -0
  241. package/dist/commands/ecdn/firewall/create.d.ts +1 -0
  242. package/dist/commands/ecdn/firewall/delete.d.ts +1 -0
  243. package/dist/commands/ecdn/firewall/get.d.ts +1 -0
  244. package/dist/commands/ecdn/firewall/list.d.ts +1 -0
  245. package/dist/commands/ecdn/firewall/reorder.d.ts +1 -0
  246. package/dist/commands/ecdn/firewall/update.d.ts +1 -0
  247. package/dist/commands/ecdn/logpush/jobs/create.d.ts +1 -0
  248. package/dist/commands/ecdn/logpush/jobs/delete.d.ts +1 -0
  249. package/dist/commands/ecdn/logpush/jobs/get.d.ts +1 -0
  250. package/dist/commands/ecdn/logpush/jobs/list.d.ts +1 -0
  251. package/dist/commands/ecdn/logpush/jobs/update.d.ts +1 -0
  252. package/dist/commands/ecdn/logpush/ownership.d.ts +1 -0
  253. package/dist/commands/ecdn/mrt-rules/create.d.ts +1 -0
  254. package/dist/commands/ecdn/mrt-rules/delete.d.ts +1 -0
  255. package/dist/commands/ecdn/mrt-rules/get.d.ts +1 -0
  256. package/dist/commands/ecdn/mrt-rules/rules/delete.d.ts +1 -0
  257. package/dist/commands/ecdn/mrt-rules/rules/update.d.ts +1 -0
  258. package/dist/commands/ecdn/mrt-rules/update.d.ts +1 -0
  259. package/dist/commands/ecdn/mtls/create.d.ts +1 -0
  260. package/dist/commands/ecdn/mtls/delete.d.ts +1 -0
  261. package/dist/commands/ecdn/mtls/get.d.ts +1 -0
  262. package/dist/commands/ecdn/mtls/issue.d.ts +1 -0
  263. package/dist/commands/ecdn/mtls/list.d.ts +1 -0
  264. package/dist/commands/ecdn/mtls/setup.d.ts +1 -0
  265. package/dist/commands/ecdn/origin-headers/delete.d.ts +1 -0
  266. package/dist/commands/ecdn/origin-headers/get.d.ts +1 -0
  267. package/dist/commands/ecdn/origin-headers/set.d.ts +1 -0
  268. package/dist/commands/ecdn/page-shield/notifications/create.d.ts +1 -0
  269. package/dist/commands/ecdn/page-shield/notifications/delete.d.ts +1 -0
  270. package/dist/commands/ecdn/page-shield/notifications/list.d.ts +1 -0
  271. package/dist/commands/ecdn/page-shield/policies/create.d.ts +1 -0
  272. package/dist/commands/ecdn/page-shield/policies/delete.d.ts +1 -0
  273. package/dist/commands/ecdn/page-shield/policies/get.d.ts +1 -0
  274. package/dist/commands/ecdn/page-shield/policies/list.d.ts +1 -0
  275. package/dist/commands/ecdn/page-shield/policies/update.d.ts +1 -0
  276. package/dist/commands/ecdn/page-shield/scripts/get.d.ts +1 -0
  277. package/dist/commands/ecdn/page-shield/scripts/list.d.ts +1 -0
  278. package/dist/commands/ecdn/rate-limit/create.d.ts +1 -0
  279. package/dist/commands/ecdn/rate-limit/delete.d.ts +1 -0
  280. package/dist/commands/ecdn/rate-limit/get.d.ts +1 -0
  281. package/dist/commands/ecdn/rate-limit/list.d.ts +1 -0
  282. package/dist/commands/ecdn/rate-limit/update.d.ts +1 -0
  283. package/dist/commands/ecdn/security/get.d.ts +1 -0
  284. package/dist/commands/ecdn/security/update.d.ts +1 -0
  285. package/dist/commands/ecdn/speed/get.d.ts +1 -0
  286. package/dist/commands/ecdn/speed/update.d.ts +1 -0
  287. package/dist/commands/ecdn/waf/groups/list.d.ts +1 -0
  288. package/dist/commands/ecdn/waf/groups/update.d.ts +1 -0
  289. package/dist/commands/ecdn/waf/managed-rules/list.d.ts +1 -0
  290. package/dist/commands/ecdn/waf/managed-rules/update.d.ts +1 -0
  291. package/dist/commands/ecdn/waf/migrate.d.ts +1 -0
  292. package/dist/commands/ecdn/waf/owasp/get.d.ts +1 -0
  293. package/dist/commands/ecdn/waf/owasp/update.d.ts +1 -0
  294. package/dist/commands/ecdn/waf/rules/get.d.ts +1 -0
  295. package/dist/commands/ecdn/waf/rules/list.d.ts +1 -0
  296. package/dist/commands/ecdn/waf/rules/update.d.ts +1 -0
  297. package/dist/commands/ecdn/waf/rulesets/list.d.ts +1 -0
  298. package/dist/commands/ecdn/waf/rulesets/update.d.ts +1 -0
  299. package/dist/commands/ecdn/zones/create.d.ts +1 -0
  300. package/dist/commands/ecdn/zones/list.d.ts +1 -0
  301. package/dist/commands/job/execution/delete.d.ts +1 -0
  302. package/dist/commands/job/export.d.ts +1 -0
  303. package/dist/commands/job/import-set.d.ts +1 -0
  304. package/dist/commands/job/import.d.ts +1 -0
  305. package/dist/commands/job/log.d.ts +1 -0
  306. package/dist/commands/job/run.d.ts +1 -0
  307. package/dist/commands/job/search.d.ts +1 -0
  308. package/dist/commands/job/wait.d.ts +1 -0
  309. package/dist/commands/logs/get.d.ts +1 -0
  310. package/dist/commands/logs/list.d.ts +1 -0
  311. package/dist/commands/logs/tail.d.ts +1 -0
  312. package/dist/commands/metrics/controller.d.ts +1 -0
  313. package/dist/commands/metrics/ecdn.d.ts +1 -0
  314. package/dist/commands/metrics/mrt.d.ts +1 -0
  315. package/dist/commands/metrics/ocapi.d.ts +1 -0
  316. package/dist/commands/metrics/overall.d.ts +1 -0
  317. package/dist/commands/metrics/sales.d.ts +1 -0
  318. package/dist/commands/metrics/scapi-hooks.d.ts +1 -0
  319. package/dist/commands/metrics/scapi.d.ts +1 -0
  320. package/dist/commands/metrics/third-party.d.ts +1 -0
  321. package/dist/commands/mrt/bundle/delete.d.ts +1 -0
  322. package/dist/commands/mrt/bundle/deploy.d.ts +1 -0
  323. package/dist/commands/mrt/bundle/download.d.ts +1 -0
  324. package/dist/commands/mrt/bundle/history.d.ts +1 -0
  325. package/dist/commands/mrt/bundle/list.d.ts +1 -0
  326. package/dist/commands/mrt/bundle/save.d.ts +1 -0
  327. package/dist/commands/mrt/bundle/upload-v2.d.ts +1 -0
  328. package/dist/commands/mrt/env/access-control/list.d.ts +1 -0
  329. package/dist/commands/mrt/env/b2c.d.ts +1 -0
  330. package/dist/commands/mrt/env/clone.d.ts +1 -0
  331. package/dist/commands/mrt/env/create.d.ts +1 -0
  332. package/dist/commands/mrt/env/delete.d.ts +1 -0
  333. package/dist/commands/mrt/env/get.d.ts +1 -0
  334. package/dist/commands/mrt/env/invalidate.d.ts +1 -0
  335. package/dist/commands/mrt/env/list.d.ts +1 -0
  336. package/dist/commands/mrt/env/redirect/clone.d.ts +1 -0
  337. package/dist/commands/mrt/env/redirect/create.d.ts +1 -0
  338. package/dist/commands/mrt/env/redirect/delete.d.ts +1 -0
  339. package/dist/commands/mrt/env/redirect/list.d.ts +1 -0
  340. package/dist/commands/mrt/env/update.d.ts +1 -0
  341. package/dist/commands/mrt/env/var/delete.d.ts +1 -0
  342. package/dist/commands/mrt/env/var/list.d.ts +1 -0
  343. package/dist/commands/mrt/env/var/push.d.ts +1 -0
  344. package/dist/commands/mrt/env/var/set.d.ts +1 -0
  345. package/dist/commands/mrt/org/b2c.d.ts +1 -0
  346. package/dist/commands/mrt/org/cert/create.d.ts +1 -0
  347. package/dist/commands/mrt/org/cert/delete.d.ts +1 -0
  348. package/dist/commands/mrt/org/cert/get.d.ts +1 -0
  349. package/dist/commands/mrt/org/cert/list.d.ts +1 -0
  350. package/dist/commands/mrt/org/cert/restart-validation.d.ts +1 -0
  351. package/dist/commands/mrt/org/list.d.ts +1 -0
  352. package/dist/commands/mrt/org/member/add.d.ts +1 -0
  353. package/dist/commands/mrt/org/member/get.d.ts +1 -0
  354. package/dist/commands/mrt/org/member/list.d.ts +1 -0
  355. package/dist/commands/mrt/org/member/remove.d.ts +1 -0
  356. package/dist/commands/mrt/org/member/update.d.ts +1 -0
  357. package/dist/commands/mrt/project/create.d.ts +1 -0
  358. package/dist/commands/mrt/project/delete.d.ts +1 -0
  359. package/dist/commands/mrt/project/get.d.ts +1 -0
  360. package/dist/commands/mrt/project/list.d.ts +1 -0
  361. package/dist/commands/mrt/project/member/add.d.ts +1 -0
  362. package/dist/commands/mrt/project/member/get.d.ts +1 -0
  363. package/dist/commands/mrt/project/member/list.d.ts +1 -0
  364. package/dist/commands/mrt/project/member/remove.d.ts +1 -0
  365. package/dist/commands/mrt/project/member/update.d.ts +1 -0
  366. package/dist/commands/mrt/project/notification/delete.d.ts +1 -0
  367. package/dist/commands/mrt/project/notification/get.d.ts +1 -0
  368. package/dist/commands/mrt/project/update.d.ts +1 -0
  369. package/dist/commands/mrt/save-credentials.d.ts +1 -0
  370. package/dist/commands/mrt/tail-logs.d.ts +1 -0
  371. package/dist/commands/mrt/user/api-key.d.ts +1 -0
  372. package/dist/commands/mrt/user/email-prefs.d.ts +1 -0
  373. package/dist/commands/mrt/user/profile.d.ts +1 -0
  374. package/dist/commands/scaffold/init.js +2 -1
  375. package/dist/commands/scaffold/init.js.map +1 -1
  376. package/dist/commands/scapi/custom/status.d.ts +1 -0
  377. package/dist/commands/scapi/schemas/get.d.ts +1 -0
  378. package/dist/commands/scapi/schemas/list.d.ts +1 -0
  379. package/dist/commands/setup/ide/tsserver-plugin.d.ts +1 -0
  380. package/dist/commands/setup/ide/vscode-types.d.ts +1 -0
  381. package/dist/commands/setup/index.js +4 -3
  382. package/dist/commands/setup/index.js.map +1 -1
  383. package/dist/commands/setup/inspect.d.ts +1 -0
  384. package/dist/commands/setup/inspect.js +17 -2
  385. package/dist/commands/setup/inspect.js.map +1 -1
  386. package/dist/commands/setup/instance/create.d.ts +1 -0
  387. package/dist/commands/setup/instance/list.d.ts +1 -0
  388. package/dist/commands/setup/instance/remove.d.ts +1 -0
  389. package/dist/commands/setup/instance/set-active.d.ts +1 -0
  390. package/dist/commands/setup/openshell.d.ts +1 -0
  391. package/dist/commands/setup/skills.d.ts +1 -0
  392. package/dist/commands/slas/client/create.d.ts +1 -0
  393. package/dist/commands/slas/client/delete.d.ts +1 -0
  394. package/dist/commands/slas/client/get.d.ts +1 -0
  395. package/dist/commands/slas/client/list.d.ts +1 -0
  396. package/dist/commands/slas/client/open.d.ts +1 -0
  397. package/dist/commands/slas/client/update.d.ts +1 -0
  398. package/dist/commands/slas/token.d.ts +1 -0
  399. package/dist/commands/slas/token.js +2 -1
  400. package/dist/commands/slas/token.js.map +1 -1
  401. package/dist/commands/webdav/get.d.ts +1 -0
  402. package/dist/commands/webdav/mkdir.d.ts +2 -0
  403. package/dist/commands/webdav/mkdir.js +5 -3
  404. package/dist/commands/webdav/mkdir.js.map +1 -1
  405. package/dist/commands/webdav/put.d.ts +2 -0
  406. package/dist/commands/webdav/put.js +5 -3
  407. package/dist/commands/webdav/put.js.map +1 -1
  408. package/dist/commands/webdav/rm.d.ts +1 -0
  409. package/dist/help.d.ts +25 -0
  410. package/dist/help.js +96 -0
  411. package/dist/help.js.map +1 -0
  412. package/dist/lib/scaffold/generate-helper.js +3 -2
  413. package/dist/lib/scaffold/generate-helper.js.map +1 -1
  414. package/dist/lib/skills.d.ts +19 -0
  415. package/dist/lib/skills.js +75 -0
  416. package/dist/lib/skills.js.map +1 -0
  417. package/dist/utils/cip/command.d.ts +1 -0
  418. package/dist/utils/ecdn/zone-command.d.ts +1 -0
  419. package/dist/utils/slas/client.d.ts +1 -0
  420. package/oclif.manifest.json +10994 -7653
  421. package/package.json +11 -5
@@ -0,0 +1,73 @@
1
+ # Loader patterns
2
+
3
+ See also `docs/README-DATA.md`, `docs/README-SUSPENSE.md` and the "Performance & Data Rules" in `AGENTS.md` in your project.
4
+
5
+ ## Critical versus streamed
6
+
7
+ | Data | Treatment |
8
+ |---|---|
9
+ | Entity that decides status (product, category, order) | `await`; map SCAPI 404 to `throw new Response(msg, { status: 404 })` |
10
+ | Data visible in the first viewport, SEO tags, JSON-LD source | `await` |
11
+ | Page Designer page for the LCP region | `await` the page and render `<Region critical>` (see `storefront-next:sfnext-page-designer`) |
12
+ | Below the fold, recommendations, reviews, secondary panels | return the promise |
13
+ | Short-TTL data (availability about 60 s) that is not the LCP | prefer streaming |
14
+ | Needs a user gesture | fetcher, not loader |
15
+
16
+ Start every independent request before the first `await` so they run in parallel:
17
+
18
+ ```ts
19
+ const clients = createApiClients(context);
20
+ const extrasPromise = loadExtras(context, id); // started, not awaited
21
+ const product = await fetchProductById(context, id); // critical
22
+ return { product, extras: extrasPromise };
23
+ ```
24
+
25
+ ## Stable promises
26
+
27
+ Compose dependent work inside the loader (`extrasPromise.then(...)` there, never in render). A new promise object per render restarts Suspense and flashes the fallback. Do not wrap promises in `useMemo`. If a component must derive one, pin it with `useState(() => ...)` or re-pin via `useRef` keyed on the inputs. Full rules in `docs/README-SUSPENSE.md`.
28
+
29
+ A streamed promise that can reject needs an error path: use `<Await errorElement={...}>` or make the loader promise resolve to a fallback value (`.catch(() => [])`) when degraded output is acceptable, and log inside the loader.
30
+
31
+ ## Consuming a promise
32
+
33
+ ```tsx
34
+ <Suspense fallback={<RecommendationsSkeleton />}>
35
+ <Await resolve={loaderData.recommendations} errorElement={null}>
36
+ {(items) => <Recommendations items={items} />}
37
+ </Await>
38
+ </Suspense>
39
+ ```
40
+
41
+ - One `<Suspense>` per independent async operation; siblings may resolve independently.
42
+ - The skeleton must reserve the final height (no `fallback={null}` above the fold).
43
+ - A component that reads a promise with `use()` must have a `<Suspense>` ancestor, otherwise it blocks the first byte.
44
+ - For product listings reuse `DeferredProductGrid` (`@/components/product-grid/deferred`).
45
+
46
+ ## Shared layout data
47
+
48
+ Layout loaders (for example `_app.tsx` navigation) stream their data and child routes read it with `useRouteLoaderData('routes/_app')`. Put data that many routes need in the lowest common layout, not in each page.
49
+
50
+ ## Request context
51
+
52
+ Loaders receive `context` (`Route.LoaderArgs`). Useful accessors:
53
+
54
+ | Need | Import |
55
+ |---|---|
56
+ | Logger | `getLogger` from `@/lib/logger.server` |
57
+ | Site, locale, currency | `siteContext` from `@salesforce/storefront-next-runtime/site-context` via `context.get(siteContext)` |
58
+ | Config | `getConfig` from `@salesforce/storefront-next-runtime/config` |
59
+ | Session | `getAuth` from `@/middlewares/auth.server` |
60
+ | Basket | `getBasket`, `getBasketSnapshot`, `ensureBasketId` from `@/middlewares/basket.server` |
61
+
62
+ Middleware order is defined in `src/root.tsx` (`export const middleware`); add new request-wide state there with `createContext`/middleware instead of re-deriving it in each loader.
63
+
64
+ ## Shopper context and personalization
65
+
66
+ Shopper context (customer segments, source codes, custom qualifiers) is applied by `shopper-context` middleware and read in components with `useShopperContext`. Read `docs/README-SHOPPER-CONTEXT.md` before changing it. Personalized endpoints must not be cached as shared responses.
67
+
68
+ ## Pitfalls
69
+
70
+ - `Promise.all([...])` over critical and non-critical together re-blocks the loader; await only the critical set.
71
+ - Mutating `loaderData` on the client is unsupported; derive in the loader.
72
+ - Do not add `clientLoader`.
73
+ - Shaping or normalizing data in render (lookup maps, chained passes) belongs in the loader.
@@ -0,0 +1,39 @@
1
+ # `useScapiFetcher`
2
+
3
+ `import { useScapiFetcher } from '@/hooks/use-scapi-fetcher'`
4
+
5
+ A typed wrapper over React Router's `useFetcher` that calls a Shopper client method through a single resource route (`src/routes/resource.api.client.$resource.ts`). The request is encoded (base64url of `[client, method, options]`) into `/resource/api/client/:resource`, executed on the server, and the SCAPI `data` is returned unwrapped.
6
+
7
+ ```tsx
8
+ const product = useScapiFetcher('shopperProducts', 'getProduct', {
9
+ params: { path: { id: variantId }, query: { expand: ['availability', 'prices'] } },
10
+ });
11
+
12
+ useEffect(() => {
13
+ if (variantId && product.state === 'idle' && !product.data && !product.errors) void product.load();
14
+ }, [variantId, product]); // keep deps stable; see checklist
15
+ ```
16
+
17
+ Returned object: `.load()` (GET), `.submit(payload, opts)` (mutation), `.data`, `.errors`, `.success`, plus the fetcher fields such as `.state`.
18
+
19
+ Real users: `src/providers/basket.tsx` (`shopperBasketsV2.getBasket`) and `src/components/cart-item-modal/*` (`shopperProducts.getProduct`).
20
+
21
+ ## Server allowlist (`src/lib/scapi/resource-policy.ts`)
22
+
23
+ - Loaders: `shopperBasketsV2.getBasket`, `shopperProducts.getProduct`, `shopperProducts.getProducts`, `shopperSearch.getSearchSuggestions`.
24
+ - Actions: `shopperCustomers.createCustomerAddress`, `updateCustomerAddress`, `removeCustomerAddress`, `updateCustomer`, `updateCustomerPassword`.
25
+
26
+ Everything else is rejected. `organizationId`, `siteId` and `locale` are set by the server, and request bodies and headers are sanitized. The older "helpers" overload is unsupported.
27
+
28
+ Need something else (recommendations, category products, your own custom API)? Create a `resource.*` route with a `loader`. Pattern: same-origin check, input validation, `Cache-Control: no-store` for personalized output (`resource.recommendations.ts`, `resource.category-products.ts`). To allow another client call, change `resource-policy.ts` deliberately and add a test; do not widen it casually.
29
+
30
+ ## Related hooks
31
+
32
+ - `useScapiFetcherEffect(fetcher, { onSuccess, onError })` runs callbacks once per completed request.
33
+ - `useScapiFetchClient` (`@/hooks/use-scapi-fetch`) is a lower-level, non-fetcher variant for one-off calls.
34
+
35
+ ## When not to use it
36
+
37
+ If the data is knowable at request time, fetch it in the loader. Mounting a component that fires `useScapiFetcher().load()` in an effect for data the route could have streamed adds a waterfall; see the performance review checklist in `storefront-next:sfnext-performance`.
38
+
39
+ Calls made through `useScapiFetcher().load()` are fetcher loads, not submissions, so they do not revalidate other loaders. `.submit()` is a submission and does.
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: sfnext-deployment
3
+ description: >-
4
+ Build and deploy a Storefront Next storefront: `pnpm build`, `pnpm push` / `sfnext push` to Managed Runtime (MRT),
5
+ MRT credentials (MRT_API_KEY, MRT_PROJECT, MRT_TARGET), syncing env vars with `pnpm config:push-env`, deploying
6
+ the base cartridge and Page Designer metadata (`pnpm cartridge:generate|validate|deploy`), the shipped GitHub
7
+ Actions deploy workflow, bundle size checks, the pre-launch checklist, and upgrading a project (template vs SDK
8
+ compatibility, react-router pin). Use when a push fails or is rejected, a deployed site returns 500 or shows
9
+ stale Page Designer components, "deploy to staging/production", or before go-live.
10
+ Do not use for generic MRT project/environment/redirect/member management or log tailing (use `b2c-cli:b2c-mrt`),
11
+ for config.server.ts and PUBLIC__ variable rules (use `storefront-next:sfnext-configuration`), or for creating
12
+ the project (use `storefront-next:sfnext-project-setup`).
13
+ ---
14
+
15
+ # Storefront Next Deployment
16
+
17
+ A storefront ships as two independent deployments:
18
+
19
+ | Deployment | Target | Command |
20
+ | --- | --- | --- |
21
+ | App bundle (SSR server + client assets) | Managed Runtime | `pnpm build` then `pnpm push` |
22
+ | Base cartridge (Page Designer metadata, notification Custom API) | B2C Commerce instance (WebDAV code version) | `pnpm cartridge:deploy` |
23
+
24
+ If Business Manager Storefront Setup created your project, reuse its MRT project, environments, and SLAS client. Guides: [deployment](https://developer.salesforce.com/docs/commerce/sfnext/guide/sfnext-push-mrt-auto.html), [launch](https://developer.salesforce.com/docs/commerce/sfnext/guide/sfnext-mrt-launch-storefront.html).
25
+
26
+ ## Build
27
+
28
+ ```bash
29
+ pnpm build # extension locales + config aggregation, cartridge:generate, react-router build -> build/
30
+ pnpm start # preview the production build at http://localhost:3000
31
+ pnpm bundlesize # build with bundle size limits enforced
32
+ ```
33
+
34
+ Run `pnpm typecheck`, `pnpm lint`, and `pnpm test` before pushing. Node 24 is required locally and on MRT (`runtime.ssrParameters.ssrFunctionNodeVersion: '24.x'`).
35
+
36
+ ## Push to Managed Runtime
37
+
38
+ `push` does **not** build; it fails if `build/` is missing.
39
+
40
+ ```bash
41
+ pnpm build && pnpm push # upload only (not deployed to an env unless a target is set)
42
+ pnpm push -- -m "Release 42" -e staging --wait # deploy to an env and wait
43
+ ```
44
+
45
+ | Need | Provide |
46
+ | --- | --- |
47
+ | Credentials | `MRT_API_KEY` (or `--api-key`, `--credentials-file`, `~/.mobify`); `MRT_CLOUD_ORIGIN` for a non-default MRT origin |
48
+ | Project slug | `MRT_PROJECT` / `-p` / `SFCC_MRT_PROJECT` / dw.json `mrtProject` (set it explicitly; push errors without one) |
49
+ | Target env | `MRT_TARGET` / `-e`. Required with `--wait`. Without it the bundle uploads but is not deployed |
50
+
51
+ 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`.
52
+
53
+ 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.
54
+
55
+ ## Environment variables on MRT
56
+
57
+ `.env` is **not** uploaded by `push`. Set runtime config on the MRT environment:
58
+
59
+ ```bash
60
+ pnpm config:push-env # b2c mrt env var push: reads .env, shows a diff, asks to confirm
61
+ b2c mrt env var push -f .env.staging -p my-project -e staging --yes # explicit file, skips prompt
62
+ b2c mrt env var set PUBLIC__app__defaultSiteId=MySite -p my-project -e staging
63
+ pnpm sfnext config inspect --project my-project --environment staging # see what is applied
64
+ ```
65
+
66
+ `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](https://developer.salesforce.com/docs/commerce/sfnext/guide/sfnext-mrt-environment-vars.html). Rules for what to set: `storefront-next:sfnext-configuration`.
67
+
68
+ ## Cartridge deployment
69
+
70
+ ```bash
71
+ pnpm cartridge:generate # Page Designer metadata from decorators (also run by pnpm build)
72
+ pnpm cartridge:validate # validate generated JSON
73
+ pnpm cartridge:deploy # upload cartridges/ to the instance
74
+ pnpm cartridge:deploy -- --delete --reload # wipe old files first, then activate the code version
75
+ ```
76
+
77
+ - Deployment is **not** part of `pnpm push` and is manual by default.
78
+ - Needs an instance (`-s/--server` or `SFCC_SERVER`), WebDAV credentials, and either `--code-version` or OAuth credentials to discover the active version (`--reload` also needs OAuth with OCAPI `code_versions` access). Settings resolve from flags, env, or `dw.json`; see `b2c-cli:b2c-code` for the shared auth model.
79
+ - Redeploy whenever Page Designer decorators or attribute definitions change; stale components in Business Manager mean the cartridge is behind.
80
+ - 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`).
81
+
82
+ ## CI/CD
83
+
84
+ 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.
85
+
86
+ ## Pre-launch checklist
87
+
88
+ 1. `pnpm typecheck && pnpm lint && pnpm test` pass; `pnpm bundlesize` within limits.
89
+ 2. MRT variables set on the target env: your own client ID, organization ID, short code, site(s); `pnpm config:inspect` shows no unintended demo values.
90
+ 3. Demo analytics IDs/hosts in `app.engagement.adapters` replaced or disabled.
91
+ 4. `images.host` switched from the DIS staging host to production; `realmHostMappings` for custom domains.
92
+ 5. Cartridge deployed and code version activated; SLAS scopes registered; Page Designer pages publish and render.
93
+ 6. SLAS redirect URIs include every production domain; cookie domain and Business Manager Hybrid Auth level agree if used (`references/MRT-DEPLOYMENT.md`).
94
+ 7. `url.seoRoutes` has an entry per active site if enabled (protected: needs a rebuild).
95
+ 8. Security headers/CSP and Turnstile reviewed (`storefront-next:sfnext-security`); robots and sitemap handled (`storefront-next:sfnext-seo`).
96
+ 9. Smoke test after deploy: home, PLP, PDP, cart, login, checkout, and a Page Designer page.
97
+
98
+ ## Upgrading a project
99
+
100
+ 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.
101
+
102
+ ## Troubleshooting
103
+
104
+ | Symptom | Cause / fix |
105
+ | --- | --- |
106
+ | `Build directory ... does not exist` | Run `pnpm build` before `pnpm push` |
107
+ | Push: project slug required | Set `MRT_PROJECT` (or `-p`) |
108
+ | Push: credentials required / 401 | `MRT_API_KEY` missing or for a different MRT user; check `--credentials-file` |
109
+ | `--wait` error about environment | Add `-e <env>` or `MRT_TARGET` |
110
+ | 500 after deploy | Required `PUBLIC__` variables missing on that MRT environment; `pnpm sfnext config inspect --environment <env>`; tail logs (`b2c-cli:b2c-mrt`) |
111
+ | 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` |
112
+ | Stale Page Designer components | Cartridge not regenerated/deployed or code version not activated |
113
+ | Build fails on client chunk importing server config | `server-config.ts` imported from client code |
114
+
115
+ ## Related Skills
116
+
117
+ - `storefront-next:sfnext-project-setup` - Scripts, CLI reference, first run
118
+ - `storefront-next:sfnext-configuration` - Config and env var rules, multi-site/base path/cookie domain
119
+ - `storefront-next:sfnext-page-designer` - Decorators and cartridge metadata
120
+ - `storefront-next:sfnext-performance` - Bundle size and Lighthouse
121
+ - `storefront-next:sfnext-quality-gates` - Pre-push lint/type/test gates
122
+ - `b2c-cli:b2c-mrt` - MRT projects, environments, bundles, env vars, redirects, logs
123
+ - `b2c-cli:b2c-code` - Code version and cartridge deploy with the b2c CLI
124
+
125
+ ## Finding more
126
+
127
+ 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`.
@@ -0,0 +1,59 @@
1
+ # Managed Runtime Deployment Reference
2
+
3
+ ## What MRT provides
4
+
5
+ Server-side rendering on Node 24, a CDN in front of the SSR function and static bundle assets, separate environments (for example development, staging, production), and versioned bundles that can be re-deployed. Project, environment, member, redirect, and certificate management is done with `b2c mrt ...` (`b2c-cli:b2c-mrt`) or Runtime Admin.
6
+
7
+ ## Push flow
8
+
9
+ ```
10
+ pnpm build -> build/
11
+ pnpm push -> sfnext push: creates a bundle from build/, uploads it to the project
12
+ -> with a target env (MRT_TARGET / -e): deploys it; with --wait: blocks until done
13
+ ```
14
+
15
+ Precedence for project and environment: CLI flag, then `MRT_PROJECT` / `MRT_TARGET`, then `SFCC_MRT_PROJECT` / `SFCC_MRT_ENVIRONMENT`, then `dw.json` (`mrtProject`, `mrtEnvironment`). Credentials: `--api-key` / `MRT_API_KEY`, or `--credentials-file` / `MRT_CREDENTIALS_FILE`, or `~/.mobify`.
16
+
17
+ Send extra flags through pnpm with `--`: `pnpm push -- --wait -e production`.
18
+
19
+ ## What push sends to MRT
20
+
21
+ - The bundle (server build + client assets).
22
+ - SSR parameters from `config.server.ts` `runtime.ssrParameters` (`ssrFunctionNodeVersion`, `envBasePath`) and `runtime.ssrOnly` / `ssrShared`.
23
+
24
+ It does not send `.env` values or cartridges.
25
+
26
+ ## Environment variables
27
+
28
+ Set per environment in Runtime Admin or with the b2c CLI (`pnpm config:push-env`, `b2c mrt env var set|push|list|delete`). Changes to variables apply to that environment; confirm the behavior in Runtime Admin for your project. Server-only secrets (`COMMERCE_API_SLAS_SECRET` for private clients, `GUEST_ORDER_LOOKUP_COOKIE_SECRET`, `MARKETING_CLOUD_*`) go in unprefixed. `PUBLIC__` variables are merged into config and visible in the browser. Limits: see Salesforce's [constraints](https://developer.salesforce.com/docs/commerce/sfnext/guide/sfnext-mrt-environment-vars.html#constraints).
29
+
30
+ Example of per-environment application variables (values are yours):
31
+
32
+ ```bash
33
+ PUBLIC__app__commerce__api__clientId=<slas-client-id>
34
+ PUBLIC__app__commerce__api__organizationId=f_ecom_<realm>_<instance>
35
+ PUBLIC__app__commerce__api__shortCode=<short-code>
36
+ PUBLIC__app__defaultSiteId=<site-id>
37
+ PUBLIC__app__commerce__sites='[{"id":"<site-id>","defaultLocale":"en-US","defaultCurrency":"USD","supportedLocales":[{"id":"en-US","preferredCurrency":"USD"}],"supportedCurrencies":["USD"]}]'
38
+ ```
39
+
40
+ ## Domains, base path, cookies
41
+
42
+ - Many domains on one environment: register each as an external hostname in Runtime Admin, add SLAS redirect URIs per domain, configure `images.realmHostMappings`. The public origin is resolved per request from `X-Forwarded-Host`.
43
+ - Several storefronts under one domain: give each environment a distinct `runtime.ssrParameters.envBasePath` (`/shop-a`); the CDN routes on the first path segment; the value reaches MRT via `pnpm push`.
44
+ - Shared cookies across subdomains: `app.cookies.domain` plus Business Manager Hybrid Auth cookie-domain level `2`.
45
+
46
+ Details: `storefront-next:sfnext-configuration` `references/MULTI-SITE-URLS.md`. If the domain is also fronted by eCDN, manage zones and rules with `b2c-cli:b2c-ecdn`.
47
+
48
+ ## Rollback
49
+
50
+ Each push creates a bundle. To return to an earlier version, list bundles and deploy one to the environment: `b2c mrt bundle history -p <project> -e <env>` and `b2c mrt bundle deploy <bundleId> -p <project> -e <env>`. Cartridge changes roll back separately by activating a previous code version (`b2c-cli:b2c-code`).
51
+
52
+ ## Verifying a deployment
53
+
54
+ 1. Home, category, product, cart, and checkout pages render.
55
+ 2. Products and prices load (SCAPI connectivity, correct site).
56
+ 3. Login/logout, including social or passwordless if enabled.
57
+ 4. A Page Designer page renders and the cartridge/code version is current.
58
+ 5. Response headers (CSP) and cookies have the expected `Domain` (`curl -sI`).
59
+ 6. Logs show no repeated `[Config Warning]` lines about ignored variables.
@@ -0,0 +1,118 @@
1
+ ---
2
+ name: sfnext-extensions
3
+ description: >-
4
+ Add or remove modular features in a Storefront Next project with the extension system: src/extensions/<name>/ folders, target-config.json (UITarget components, contextProviders, actionHooks), sfcc.-prefixed UITarget ids, extension routes, per-extension config.ts and locales, SFDC_EXT_ integration markers, the `sfnext extensions create|install|remove|list` commands, and the agent-driven instructions/*.mdc install flow. Use when inserting a component into a UITarget slot (for example sfcc.header.before.cart or sfcc.pdp.bnpl.message), adding a checkout action hook, installing or removing store locator, BOPIS, multiship or a demo extension, listing extension points with pnpm extensions:list, or deciding whether to extend, restyle, or edit the base at all. Do not use for styling or brand changes (use `storefront-next:sfnext-theming`), for new merchant-editable Page Designer blocks (use `storefront-next:sfnext-page-designer`), or for analytics/engagement adapters (use `storefront-next:sfnext-analytics-consent`).
5
+ ---
6
+
7
+ # Storefront Next Extensions
8
+
9
+ An extension is a self-contained folder under `src/extensions/<name>/` that adds UI, routes, providers, translations, config and server hooks to the storefront without rewriting base files. The base declares named slots (`<UITarget targetId="..." />`); an extension's `target-config.json` says which of its components fill which slot.
10
+
11
+ Your project ships with several extensions already (store locator, BOPIS, multiship, and demo extensions such as BNPL and ratings and reviews). Look at them before building: they are the reference implementations. See [Extension Examples](references/EXTENSION-EXAMPLES.md).
12
+
13
+ ## Decision gate: should this be an extension?
14
+
15
+ Run this before writing code; the full walkthrough is in [Base Audit](references/BASE-AUDIT.md).
16
+
17
+ 1. Trace the route in `src/routes/` down to the place you want to change. Does the base already render equivalent content there?
18
+ 2. Already rendered: restyle it (tokens or a component variant, see `storefront-next:sfnext-theming`) or fill an existing slot; do not add a parallel copy.
19
+ 3. Not rendered and a slot exists: write an extension.
20
+ 4. Not rendered and no slot fits: edit the base route or component directly (you own the whole project) and, if it is a reusable seam, add a `<UITarget>` there so later extensions can plug in.
21
+
22
+ Discover what already exists:
23
+
24
+ ```bash
25
+ pnpm extensions:list # all UITarget ids and server action hook ids (add --json for tooling)
26
+ sfnext extensions list # installed extensions
27
+ rg "UITarget" src/ # where a slot is rendered
28
+ ```
29
+
30
+ ## Structure
31
+
32
+ ```
33
+ src/extensions/my-extension/
34
+ ├── target-config.json # which components/providers/hooks plug in where
35
+ ├── components/ # UI, including the components named in target-config.json
36
+ ├── routes/ # auto-registered routes (flat-route file naming)
37
+ ├── providers/ # context providers (listed in target-config.json)
38
+ ├── hooks/ context/ middlewares/ stores/ # as needed
39
+ ├── locales/<lang>/translations.json
40
+ ├── config.ts # optional client-side defaults
41
+ ├── server-config.ts # optional server-only defaults
42
+ └── README.md
43
+ ```
44
+
45
+ Create the scaffold with `sfnext extensions create -n "My Extension" -d "What it does"` (adds the folder, a README and an entry in `src/extensions/config.json`). Import across the project with the normal alias: `@/extensions/my-extension/...`. There is no `@extensions` alias.
46
+
47
+ ## target-config.json
48
+
49
+ ```json
50
+ {
51
+ "components": [
52
+ { "targetId": "sfcc.header.before.cart", "path": "extensions/my-extension/components/header/badge.tsx", "order": 0 }
53
+ ],
54
+ "contextProviders": [
55
+ { "path": "extensions/my-extension/providers/my-provider.tsx", "order": 0 }
56
+ ],
57
+ "actionHooks": [
58
+ { "hookId": "sfcc.checkout.payments.afterSubmitPayment", "handler": "extensions/my-extension/hooks/after-payment.ts", "order": 0 }
59
+ ]
60
+ }
61
+ ```
62
+
63
+ - `path` is relative to `src/` and points at a module whose default export is the component (no required props; read context or hooks inside). Multiple components on one slot render in ascending `order`; duplicate orders warn because their order is not deterministic.
64
+ - A slot without children is a replacement slot. A slot that wraps base content (`<UITarget targetId="..."><Base /></UITarget>`) is a wrapper slot: the extension component receives the base content as children.
65
+ - Optional per component: `"enabled": false` to switch it off, and `"hint"` as a label for the dev-mode overlay. A top-level `"devOnly": true` skips the whole file in production builds.
66
+ - Extension components only inject when a `target-config.json` exists in `src/extensions/<name>/`.
67
+ - Every `targetId` must exist as a `<UITarget>` in the source; otherwise the build fails and names the orphan. Ids are namespaced: use the exact `sfcc.`-prefixed ids reported by `pnpm extensions:list` (for example `sfcc.header.before.cart`, `sfcc.pdp.bnpl.message`, `sfcc.pdp.reviews.section`, `sfcc.cart.orderSummary.before`).
68
+ - In `pnpm dev`, UITarget dev mode shows markers so you can see which slots exist and what fills them.
69
+
70
+ Server-side hooks (`actionHooks`, checkout steps) have their own semantics: [Action Hooks](references/ACTION-HOOKS.md).
71
+
72
+ ## Routes, translations, config
73
+
74
+ - **Routes**: any file in `routes/` is merged into the route tree with React Router flat-route naming: `_app.store-locator.tsx` (inside the app layout), `action.set-selected-store.ts` (action), `resource.stores.ts` (resource route). See `src/extensions/store-locator/routes/`.
75
+ - **Translations**: `locales/<lang>/translations.json` is namespaced `ext` + PascalCase folder name (`my-extension` -> `extMyExtension`): `useTranslation('extMyExtension')`. `pnpm dev` and `pnpm build` run `pnpm locales:aggregate-extensions` for you and write `src/extensions/locales/`; that folder is generated, do not edit it.
76
+ - **Client config**: `config.ts` default-exports a plain, JSON-serializable object. It is merged into `config.app.extension.<camelName>` (read with `useConfig()` in components or `getConfig()` on the server) and can be overridden per environment with `PUBLIC__app__extension__<camelName>__<key>`. It is exposed to the browser: never put secrets there.
77
+ - **Server-only config**: `server-config.ts` lands at `config.app.serverExtension.<camelName>`, has no `PUBLIC__` override, is unreachable from client code (the build fails if a client chunk imports it), and is read with `getConfig(context)` in loaders, actions and middleware.
78
+ - `pnpm config:aggregate-extensions` (also run by dev and build) writes `src/extensions/config/`; generated, do not edit. Folder names must be letters, digits and hyphens starting with a letter. See `docs/README-CONFIG.md`.
79
+
80
+ ## Integration markers
81
+
82
+ Extensions that modify base files mark their edits with comments so they can be installed and removed cleanly:
83
+
84
+ ```typescript
85
+ selectedStoreMiddleware /** @sfdc-extension-line SFDC_EXT_STORE_LOCATOR */,
86
+
87
+ // @sfdc-extension-block-start SFDC_EXT_STORE_LOCATOR
88
+ import { StoreLocatorProvider } from '@/extensions/store-locator/providers/store-locator';
89
+ // @sfdc-extension-block-end SFDC_EXT_STORE_LOCATOR
90
+
91
+ /** @sfdc-extension-file SFDC_EXT_STORE_LOCATOR */ // marks an entire file as belonging to the extension
92
+ ```
93
+
94
+ Use them when the extension needs edits outside its folder (middleware registration, a nav link, a loader) and you want `sfnext extensions remove` to be able to undo them. Each marker name (`SFDC_EXT_*`) is a key in `src/extensions/config.json`. Install, remove and marker details: [CLI and Install](references/CLI-AND-INSTALL.md).
95
+
96
+ ## Removing or replacing a demo extension
97
+
98
+ BNPL, customer preferences, ratings and reviews, and product content ship with mock fixtures. To integrate a real provider, replace the bodies of their API functions (for example `src/extensions/bnpl/lib/api/bnpl.server.ts`). To drop one, use `sfnext extensions remove -e SFDC_EXT_BNPL`, then run `pnpm locales:aggregate-extensions`. `docs/README-FEATURE-STUBS.md` describes finding stubs with `grep -r "@feature-stub" src/`.
99
+
100
+ ## Best practices
101
+
102
+ 1. Keep the extension self-contained; reach into the base only through slots, hooks and markers.
103
+ 2. Prefer a slot over editing a base file; add a slot when you keep editing the same spot.
104
+ 3. Use `order` deliberately and give each slot entry a distinct value.
105
+ 4. Import via `@/extensions/...` and keep translations in the extension's own namespace.
106
+ 5. After adding a slot, extension or locale, run `pnpm dev` once so the aggregation and registries regenerate, and commit nothing from `src/extensions/locales/` or `src/extensions/config/` by hand.
107
+
108
+ ## Related Skills
109
+
110
+ - `storefront-next:sfnext-overview` - project map and where things live
111
+ - `storefront-next:sfnext-components` - component conventions used inside extensions
112
+ - `storefront-next:sfnext-routing` - how extension routes join the route tree
113
+ - `storefront-next:sfnext-i18n` - translation namespaces and locale files
114
+ - `storefront-next:sfnext-configuration` - `config.ts` layering and `PUBLIC__` overrides
115
+ - `storefront-next:sfnext-theming` - token and brand changes that do not need an extension
116
+ - `storefront-next:sfnext-commerce-features` - checkout, multiship, BOPIS flows
117
+ - `storefront-next:sfnext-page-designer` - merchant-editable blocks
118
+ - `b2c:b2c-hooks` - B2C platform-side hooks (different from Storefront Next action hooks)
@@ -0,0 +1,57 @@
1
+ # Action Hooks
2
+
3
+ Action hooks let an extension run server-side code at fixed points in the checkout actions (fraud checks, address verification, payment enrichment) without editing the action files. UI slots are separate; see the main skill.
4
+
5
+ ## Available hook ids
6
+
7
+ The ids live in `ACTION_HOOK_IDS` in `src/targets/action-hook.server.ts`; `pnpm extensions:list` prints them too.
8
+
9
+ | Constant | Hook id |
10
+ |----------|---------|
11
+ | `CHECKOUT_FRAUD_AFTER_SUBMIT_CONTACT_INFO` | `sfcc.checkout.fraud.afterSubmitContactInfo` |
12
+ | `CHECKOUT_ADDRESS_VERIFICATION_AFTER_SUBMIT_SHIPPING_ADDRESS` | `sfcc.checkout.addressVerification.afterSubmitShippingAddress` |
13
+ | `CHECKOUT_SHIPPING_AFTER_METHODS_FETCH` | `sfcc.checkout.shipping.afterMethodsFetch` |
14
+ | `CHECKOUT_SHIPPING_AFTER_METHOD_SELECT` | `sfcc.checkout.shipping.afterMethodSelect` |
15
+ | `CHECKOUT_PAYMENTS_AFTER_SUBMIT_PAYMENT` | `sfcc.checkout.payments.afterSubmitPayment` |
16
+ | `CHECKOUT_FRAUD_BEFORE_PLACE` | `sfcc.checkout.fraud.beforePlace` (blocking) |
17
+ | `CHECKOUT_PAYMENTS_BEFORE_PLACE_ORDER` | `sfcc.checkout.payments.beforePlaceOrder` (blocking) |
18
+ | `CHECKOUT_PAYMENTS_AFTER_PLACE_ORDER` | `sfcc.checkout.payments.afterPlaceOrder` |
19
+
20
+ ## Register a handler
21
+
22
+ ```json
23
+ {
24
+ "actionHooks": [
25
+ { "hookId": "sfcc.checkout.fraud.beforePlace", "handler": "extensions/my-extension/hooks/fraud-check.ts", "order": 0 }
26
+ ]
27
+ }
28
+ ```
29
+
30
+ `handler` is a path relative to `src/`; the module's default export is the handler. It receives the hook context (`{ data, actionContext }`) and returns the (optionally modified) context, or nothing to pass it through.
31
+
32
+ ```typescript
33
+ import { ActionHookError } from '@/targets/action-hook.server';
34
+ import type { ActionHookContext } from '@/targets/action-hook.server';
35
+
36
+ export default async function fraudCheck(context: ActionHookContext) {
37
+ const risky = await scoreOrder(context.data); // your own server-side call
38
+ if (risky) {
39
+ throw new ActionHookError('We could not process this order.', 'sfcc.checkout.fraud.beforePlace', 'placeOrder');
40
+ }
41
+ return context;
42
+ }
43
+ ```
44
+
45
+ The constructor is `ActionHookError(message, hookId, step)`; the step is echoed in the 400 response.
46
+
47
+ ## Semantics
48
+
49
+ - Handlers for one hook run in series as a waterfall, ordered by `order`; each receives the previous handler's output. With no handlers the original context is returned unchanged.
50
+ - Throwing `ActionHookError` aborts the action and returns an HTTP 400 JSON response with your message and the step.
51
+ - Each handler has a timeout (a few seconds); a slow handler is treated as a failure, so do not make long calls inside hooks.
52
+ - Non-blocking hooks (the default): an unexpected error is logged, the failing handler is skipped and the action continues. Blocking hooks (`fraud.beforePlace`, `payments.beforePlaceOrder` run with `blocking: true`): an unexpected error fails the action, so a broken fraud or payment check cannot silently let an order through.
53
+ - Keep handlers server-safe: they run in the action, so use `*.server` modules freely and never put secrets in client-visible config (use `server-config.ts`).
54
+
55
+ ## Adding a new hook point
56
+
57
+ Call `runHookSafe` from an action with a new id you add to `ACTION_HOOK_IDS`, as `src/routes/action.place-order.ts` does. Pass `blocking: true` only when a failure must stop the action. Then run `pnpm extensions:list` to confirm it is discovered.
@@ -0,0 +1,68 @@
1
+ # Base Audit: Extend, Restyle, or Edit
2
+
3
+ Use this before building an extension or adding a section to a page. The goal is to decide whether to extend at all, and if so at which layer, so you never ship a component that duplicates something the storefront already renders. You own the whole project, so the choices are about keeping changes small and upgrade-friendly, not about who is allowed to edit what.
4
+
5
+ ## The gate
6
+
7
+ 1. **Find what renders today.** Open the route in `src/routes/` and follow it down to the component for the area you care about.
8
+ 2. **Check every section you plan to add.** Does the base already render equivalent content there (a description, accordion, badge, banner, title)?
9
+ 3. **Branch:**
10
+ - Already rendered: change its look or behavior in place, or fill an existing slot next to it. Do not add a parallel component.
11
+ - Not rendered: continue to step 4.
12
+ 4. **Choose the layer:**
13
+
14
+ ```
15
+ Purely visual (color, font, radius, spacing)?
16
+ YES -> Token or component-variant change (storefront-next:sfnext-theming). No extension.
17
+ NO -> Does a UITarget slot exist where it belongs?
18
+ YES -> Extension filling that slot (this skill).
19
+ NO -> Is it a one-off for this storefront?
20
+ YES -> Edit the route or component directly.
21
+ NO -> Edit the base component to add a <UITarget> slot (or a render prop),
22
+ then fill it from an extension.
23
+ ```
24
+
25
+ Rule of thumb: extensions add what is missing; they do not recreate what exists. If you keep editing the same base file for the same feature, give it a slot.
26
+
27
+ ## Worked examples (real slots)
28
+
29
+ Find them with `pnpm extensions:list`. The ids below are from a current project; confirm in yours.
30
+
31
+ | You want | Already in base? | Layer |
32
+ |----------|------------------|-------|
33
+ | A "store finder" link beside the cart icon | No; `sfcc.header.before.cart` exists | Extension component on that slot (how the store locator does it) |
34
+ | An installment-payment message under the PDP price | No; `sfcc.pdp.bnpl.message` exists | Extension component on that slot (the BNPL demo does this) |
35
+ | A reviews section on the PDP | No; `sfcc.pdp.reviews.section` and `sfcc.pdp.reviews.rating` exist | Extension (the ratings and reviews demo) |
36
+ | A returns and warranty card on the PDP | Yes: `sfcc.pdp.returnsWarranty` and `sfcc.pdp.collapsibles` already render content | Replace or extend what the product-content extension fills; do not add another card |
37
+ | Make the primary button a new color | Button exists | Token change, no extension |
38
+ | A denser product tile | Tile exists | New component variant, no extension |
39
+ | A promo strip above the header, nothing fits | No slot | Edit the header component, and add a `<UITarget>` if you expect to reuse the seam |
40
+ | Block an order when a fraud check fails | Server hook `sfcc.checkout.fraud.beforePlace` exists | Action hook (see [Action Hooks](ACTION-HOOKS.md)), not UI |
41
+
42
+ ### Duplicate section (wrong) vs additive section (right)
43
+
44
+ ```
45
+ WRONG: the PDP already renders collapsible product-detail sections. The extension adds its own
46
+ accordion with the same headings -> two copies of the same content.
47
+
48
+ RIGHT: fill or extend what the existing collapsibles slot renders, or add only sections
49
+ the base lacks.
50
+ ```
51
+
52
+ ### Restyle, do not re-render
53
+
54
+ ```
55
+ WRONG: an extension renders the product title again so it can style it.
56
+ RIGHT: adjust the title's token or variant; add only the new line (for example a badge) in a slot.
57
+ ```
58
+
59
+ ## Finding slots and render points
60
+
61
+ ```bash
62
+ pnpm extensions:list # every UITarget id and action hook id, with where it is used
63
+ pnpm extensions:list -- --json # machine-readable
64
+ rg "UITarget" src/ -l # files that render slots
65
+ rg 'targetId="sfcc.pdp' src/ # slots for one area
66
+ ```
67
+
68
+ The build fails when `target-config.json` names a `targetId` that no `<UITarget>` renders, so a typo is caught immediately. If no slot suits and the page is yours to change, a direct edit is fine, after running the audit so you do not duplicate existing content.
@@ -0,0 +1,58 @@
1
+ # CLI and Install
2
+
3
+ The `sfnext` CLI (from `@salesforce/storefront-next-dev`, available in your project) manages extensions. Run commands from the project root, or pass `--project-directory`.
4
+
5
+ ```bash
6
+ sfnext extensions list # installed extensions
7
+ sfnext extensions create -n "My Extension" -d "What it does" # scaffold a new extension
8
+ sfnext extensions install -e SFDC_EXT_STORE_LOCATOR # install a registered extension
9
+ sfnext extensions remove -e SFDC_EXT_BOPIS # remove one (comma-separate several)
10
+ sfnext extensions remove -e SFDC_EXT_STORE_LOCATOR --yes # also remove dependents without prompting
11
+ pnpm extensions:list # UITarget ids and action hook ids (not the same as `list`)
12
+ ```
13
+
14
+ Run `sfnext extensions <command> --help` for the exact flags in your version.
15
+
16
+ ## create
17
+
18
+ Scaffolds `src/extensions/<kebab-name>/` (components, locales, hooks, routes, README) and registers a `SFDC_EXT_*` entry in `src/extensions/config.json`. It does not create `target-config.json` content for you; add it when you have a component to plug in.
19
+
20
+ ## install and remove
21
+
22
+ Registered extensions are listed in `src/extensions/config.json`, each with a marker key, `name`, `description`, `folder`, optional `dependencies`, and `installationInstructions` / `uninstallationInstructions` pointing at files in `instructions/`. Shipped registrations include Store Locator, BOPIS (depends on Store Locator and Multiship), Multiship, and the demo extensions BNPL, Customer Preferences, Ratings and Reviews, Product Content, and Shipping Delivery. The theme-switcher folder is present but not registered.
23
+
24
+ - `install` copies the extension folder and merges the marked snippets (see markers below) into base files from a source template repository (`--source-git-url`/`-s` overrides the default).
25
+ - `remove` reverses that and, when other installed extensions depend on the target, asks before removing them (`--yes` skips the prompt).
26
+ - Always commit or stash first and review the diff: installs touch base files such as `root.tsx`, the header and the footer.
27
+
28
+ ## Agent-driven install instructions
29
+
30
+ `instructions/*.mdc` are step-by-step prompts a coding agent can follow to install or uninstall an extension. Treat them as a starting point: they are generated from the source template repository and can lag behind your project (for example file paths or a temporary clone folder name). If a step mentions a file that does not exist in your project, prefer `sfnext extensions install`, or compare against the extension's own `README.md`.
31
+
32
+ To author instructions for your own extension (an extension whose integration edits are marked with `SFDC_EXT_*` markers):
33
+
34
+ ```bash
35
+ sfnext create-instructions -d . -c <extension-config.json> -e SFDC_EXT_MY_FEATURE
36
+ ```
37
+
38
+ Options include `-f` for the specific files that contain markers, `-b` for the template branch, and `-o` for the output directory (default `./instructions`).
39
+
40
+ ## Markers
41
+
42
+ | Marker | Meaning |
43
+ |--------|---------|
44
+ | `@sfdc-extension-line SFDC_EXT_X` | The comment line and the single line that follows it belong to the extension |
45
+ | `@sfdc-extension-block-start SFDC_EXT_X` / `@sfdc-extension-block-end SFDC_EXT_X` | Everything between belongs to the extension |
46
+ | `@sfdc-extension-file SFDC_EXT_X` | The whole file belongs to the extension and is removed on uninstall |
47
+
48
+ Rules: use the exact `SFDC_EXT_*` key from `config.json`; never nest different markers; only mark code the extension truly needs outside its folder.
49
+
50
+ ## After install or remove
51
+
52
+ ```bash
53
+ pnpm locales:aggregate-extensions # regenerate src/extensions/locales (also runs in dev/build)
54
+ pnpm config:aggregate-extensions # regenerate src/extensions/config (also runs in dev/build)
55
+ pnpm typecheck && pnpm lint
56
+ ```
57
+
58
+ Then read the extension's README for environment variables, SLAS scopes, or custom SCAPI endpoints it needs. Store Locator, for example, relies on the store data your instance exposes; check its README.