@salesforce/b2c-dx-mcp 3.2.1 → 3.3.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 (312) hide show
  1. package/bin/run.js +5 -9
  2. package/content/guidance/b2c/b2c-hooks/references/ORDER-HOOK-LIFECYCLE.md +1 -1
  3. package/content/guidance/b2c/b2c-onboarding/SKILL.md +4 -4
  4. package/content/guidance/b2c/b2c-ordering/SKILL.md +2 -2
  5. package/content/guidance/b2c/b2c-querying-data/SKILL.md +2 -2
  6. package/content/guidance/b2c/b2c-scapi-admin/SKILL.md +3 -3
  7. package/content/guidance/b2c/b2c-scapi-admin/references/CLIENT-EXAMPLES.md +4 -4
  8. package/content/guidance/b2c/b2c-scapi-shopper/SKILL.md +6 -6
  9. package/content/guidance/b2c/b2c-scapi-shopper/references/CLIENT-EXAMPLES.md +8 -9
  10. package/content/guidance/b2c-cli/b2c-cip/SKILL.md +3 -3
  11. package/content/guidance/b2c-cli/b2c-cip/references/SALES_ANALYSIS.md +1 -1
  12. package/content/guidance/b2c-cli/b2c-config/SKILL.md +31 -21
  13. package/content/guidance/b2c-cli/b2c-content/SKILL.md +1 -1
  14. package/content/guidance/b2c-cli/b2c-debug/SKILL.md +1 -1
  15. package/content/guidance/b2c-cli/b2c-docs/SKILL.md +23 -2
  16. package/content/guidance/b2c-cli/b2c-ecdn/references/ADVANCED.md +1 -1
  17. package/content/guidance/b2c-cli/b2c-job/references/IMPORT.md +1 -1
  18. package/content/guidance/b2c-cli/b2c-metrics/SKILL.md +1 -1
  19. package/content/guidance/b2c-cli/b2c-mrt/SKILL.md +3 -3
  20. package/content/guidance/b2c-cli/b2c-scapi-custom/SKILL.md +1 -1
  21. package/content/guidance/b2c-cli/b2c-scapi-schemas/SKILL.md +1 -1
  22. package/content/guidance/b2c-cli/b2c-site-import-export/SKILL.md +1 -1
  23. package/content/guidance/b2c-cli/b2c-sites/SKILL.md +1 -1
  24. package/content/guidance/b2c-cli/b2c-slas/SKILL.md +1 -1
  25. package/content/guidance/b2c-ops/b2c-checkout-triage/SKILL.md +2 -2
  26. package/content/guidance/b2c-ops/b2c-job-health/SKILL.md +2 -2
  27. package/content/guidance/b2c-ops/b2c-order-failure-triage/SKILL.md +1 -1
  28. package/content/guidance/b2c-ops/b2c-order-failure-triage/references/order-evidence.md +2 -2
  29. package/content/guidance/b2c-ops/b2c-production-triage/SKILL.md +4 -4
  30. package/content/guidance/index.json +935 -258
  31. package/content/guidance/mcp/{cip → b2c-mcp-cip}/SKILL.md +10 -8
  32. package/content/guidance/mcp/{b2c-config → b2c-mcp-config}/SKILL.md +10 -9
  33. package/content/guidance/mcp/{debugger → b2c-mcp-debugger}/SKILL.md +9 -8
  34. package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/SKILL.md +81 -10
  35. package/content/guidance/mcp/{server → b2c-mcp-server}/SKILL.md +49 -25
  36. package/content/guidance/storefront-next/sfnext-accessibility/SKILL.md +103 -0
  37. package/content/guidance/storefront-next/sfnext-accessibility/references/checklist.md +64 -0
  38. package/content/guidance/storefront-next/sfnext-analytics-consent/SKILL.md +91 -0
  39. package/content/guidance/storefront-next/sfnext-analytics-consent/references/CUSTOM-ADAPTER.md +49 -0
  40. package/content/guidance/storefront-next/sfnext-authentication/SKILL.md +86 -79
  41. package/content/guidance/storefront-next/sfnext-authentication/references/COOKIES.md +39 -0
  42. package/content/guidance/storefront-next/sfnext-authentication/references/LOGIN-FLOWS.md +59 -0
  43. package/content/guidance/storefront-next/sfnext-commerce-features/SKILL.md +67 -0
  44. package/content/guidance/storefront-next/sfnext-commerce-features/references/FEATURE-PREREQUISITES.md +37 -0
  45. package/content/guidance/storefront-next/sfnext-components/SKILL.md +98 -136
  46. package/content/guidance/storefront-next/sfnext-components/references/COMPONENT-AUTHORING.md +118 -0
  47. package/content/guidance/storefront-next/sfnext-components/references/SHAPE-TOKENS.md +51 -0
  48. package/content/guidance/storefront-next/sfnext-components/references/STORYBOOK.md +54 -0
  49. package/content/guidance/storefront-next/sfnext-components/references/TOKEN-SYSTEM.md +53 -0
  50. package/content/guidance/storefront-next/sfnext-components/references/TROUBLESHOOTING.md +19 -0
  51. package/content/guidance/storefront-next/sfnext-configuration/SKILL.md +116 -113
  52. package/content/guidance/storefront-next/sfnext-configuration/references/ENV-VARIABLES.md +55 -0
  53. package/content/guidance/storefront-next/sfnext-configuration/references/MULTI-SITE-URLS.md +137 -0
  54. package/content/guidance/storefront-next/sfnext-data-fetching/SKILL.md +100 -150
  55. package/content/guidance/storefront-next/sfnext-data-fetching/references/ACTIONS.md +53 -0
  56. package/content/guidance/storefront-next/sfnext-data-fetching/references/API-CLIENTS.md +34 -0
  57. package/content/guidance/storefront-next/sfnext-data-fetching/references/LOADERS.md +73 -0
  58. package/content/guidance/storefront-next/sfnext-data-fetching/references/SCAPI-FETCHER.md +23 -77
  59. package/content/guidance/storefront-next/sfnext-deployment/SKILL.md +83 -97
  60. package/content/guidance/storefront-next/sfnext-deployment/references/MRT-DEPLOYMENT.md +37 -68
  61. package/content/guidance/storefront-next/sfnext-extensions/SKILL.md +73 -97
  62. package/content/guidance/storefront-next/sfnext-extensions/references/ACTION-HOOKS.md +57 -0
  63. package/content/guidance/storefront-next/sfnext-extensions/references/BASE-AUDIT.md +47 -44
  64. package/content/guidance/storefront-next/sfnext-extensions/references/CLI-AND-INSTALL.md +58 -0
  65. package/content/guidance/storefront-next/sfnext-extensions/references/EXTENSION-EXAMPLES.md +49 -86
  66. package/content/guidance/storefront-next/sfnext-hybrid-storefronts/SKILL.md +59 -114
  67. package/content/guidance/storefront-next/sfnext-hybrid-storefronts/references/HYBRID-PROXY-CONFIG.md +53 -90
  68. package/content/guidance/storefront-next/sfnext-i18n/SKILL.md +96 -131
  69. package/content/guidance/storefront-next/sfnext-i18n/references/locale-config.md +35 -0
  70. package/content/guidance/storefront-next/sfnext-overview/SKILL.md +101 -0
  71. package/content/guidance/storefront-next/sfnext-page-designer/SKILL.md +152 -131
  72. package/content/guidance/storefront-next/sfnext-page-designer/references/BUSINESS-MANAGER.md +46 -0
  73. package/content/guidance/storefront-next/sfnext-page-designer/references/COMPONENT-REGISTRY.md +86 -53
  74. package/content/guidance/storefront-next/sfnext-page-designer/references/DECORATOR-PATTERNS.md +119 -131
  75. package/content/guidance/storefront-next/sfnext-page-designer/references/REVIEW-CHECKLIST.md +83 -0
  76. package/content/guidance/storefront-next/sfnext-page-designer/references/TROUBLESHOOTING.md +35 -0
  77. package/content/guidance/storefront-next/sfnext-performance/SKILL.md +75 -105
  78. package/content/guidance/storefront-next/sfnext-performance/references/PERFORMANCE-REVIEW-CHECKLIST.md +85 -0
  79. package/content/guidance/storefront-next/sfnext-performance/references/SUSPENSE-AND-STREAMING.md +58 -0
  80. package/content/guidance/storefront-next/sfnext-project-setup/SKILL.md +103 -116
  81. package/content/guidance/storefront-next/sfnext-project-setup/references/PROJECT-STRUCTURE.md +61 -99
  82. package/content/guidance/storefront-next/sfnext-project-setup/references/SCRIPTS.md +47 -0
  83. package/content/guidance/storefront-next/sfnext-project-setup/references/SFNEXT-CLI.md +63 -0
  84. package/content/guidance/storefront-next/sfnext-quality-gates/SKILL.md +70 -0
  85. package/content/guidance/storefront-next/sfnext-quality-gates/references/lint-and-budgets.md +39 -0
  86. package/content/guidance/storefront-next/sfnext-revalidation/SKILL.md +121 -0
  87. package/content/guidance/storefront-next/sfnext-revalidation/references/POLICIES-AND-TAGS.md +55 -0
  88. package/content/guidance/storefront-next/sfnext-routing/SKILL.md +86 -143
  89. package/content/guidance/storefront-next/sfnext-routing/references/ROUTE-CONVENTIONS.md +51 -51
  90. package/content/guidance/storefront-next/sfnext-routing/references/URLS-AND-SEO-ROUTES.md +22 -0
  91. package/content/guidance/storefront-next/sfnext-scapi/SKILL.md +126 -0
  92. package/content/guidance/storefront-next/sfnext-scapi/references/WORKED-EXAMPLE.md +39 -0
  93. package/content/guidance/storefront-next/sfnext-security/SKILL.md +129 -0
  94. package/content/guidance/storefront-next/sfnext-security/references/COOKIE-DOMAIN.md +39 -0
  95. package/content/guidance/storefront-next/sfnext-security/references/TURNSTILE.md +43 -0
  96. package/content/guidance/storefront-next/sfnext-seo/SKILL.md +95 -0
  97. package/content/guidance/storefront-next/sfnext-seo/references/MULTI-DOMAIN-BASE-PATH.md +17 -0
  98. package/content/guidance/storefront-next/sfnext-seo/references/SEO-ROUTES.md +31 -0
  99. package/content/guidance/storefront-next/sfnext-state-management/SKILL.md +80 -89
  100. package/content/guidance/storefront-next/sfnext-state-management/references/PATTERNS.md +45 -0
  101. package/content/guidance/storefront-next/sfnext-testing/SKILL.md +105 -138
  102. package/content/guidance/storefront-next/sfnext-testing/references/E2E.md +38 -0
  103. package/content/guidance/storefront-next/sfnext-testing/references/STORYBOOK-PATTERNS.md +73 -94
  104. package/content/guidance/storefront-next/sfnext-testing/references/UNIT-AND-ROUTE-TESTS.md +60 -0
  105. package/content/guidance/storefront-next/sfnext-theming/SKILL.md +104 -0
  106. package/content/guidance/storefront-next/sfnext-theming/references/REBRAND-CHECKLIST.md +29 -0
  107. package/dist/commands/mcp.d.ts +8 -2
  108. package/dist/commands/mcp.js +54 -20
  109. package/dist/guidance.d.ts +4 -1
  110. package/dist/guidance.js +23 -5
  111. package/dist/registry.d.ts +2 -1
  112. package/dist/registry.js +3 -3
  113. package/dist/server.d.ts +10 -0
  114. package/dist/server.js +21 -0
  115. package/dist/skill-references.js +5 -5
  116. package/dist/tools/cartridges/index.js +1 -0
  117. package/dist/tools/cip/index.js +6 -3
  118. package/dist/tools/diagnostics/debug-capture-at-breakpoint.js +1 -1
  119. package/dist/tools/diagnostics/debug-set-breakpoints.js +1 -1
  120. package/dist/tools/diagnostics/debug-start-session.js +1 -1
  121. package/dist/tools/scapi/index.d.ts +4 -1
  122. package/dist/tools/scapi/index.js +4 -2
  123. package/dist/tools/scapi/scapi-code.d.ts +2 -2
  124. package/dist/tools/scapi/scapi-code.js +17 -61
  125. package/dist/utils/types.d.ts +6 -0
  126. package/node_modules/@salesforce/b2c-agent-plugins/CHANGELOG.md +20 -0
  127. package/node_modules/@salesforce/b2c-agent-plugins/README.md +5 -0
  128. package/node_modules/@salesforce/b2c-agent-plugins/b2c/.codex-plugin/plugin.json +1 -1
  129. package/node_modules/@salesforce/b2c-agent-plugins/b2c/plugin.json +1 -1
  130. package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-hooks/references/ORDER-HOOK-LIFECYCLE.md +1 -1
  131. package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-onboarding/SKILL.md +4 -4
  132. package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-ordering/SKILL.md +2 -2
  133. package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-querying-data/SKILL.md +2 -2
  134. package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-scapi-admin/SKILL.md +3 -3
  135. package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-scapi-admin/references/CLIENT-EXAMPLES.md +4 -4
  136. package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-scapi-shopper/SKILL.md +6 -6
  137. package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-scapi-shopper/references/CLIENT-EXAMPLES.md +8 -9
  138. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/.codex-plugin/plugin.json +1 -1
  139. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/plugin.json +1 -1
  140. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-cip/SKILL.md +3 -3
  141. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-cip/references/SALES_ANALYSIS.md +1 -1
  142. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-config/SKILL.md +31 -21
  143. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-content/SKILL.md +1 -1
  144. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-debug/SKILL.md +1 -1
  145. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-docs/SKILL.md +23 -2
  146. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-ecdn/references/ADVANCED.md +1 -1
  147. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-job/references/IMPORT.md +1 -1
  148. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-metrics/SKILL.md +1 -1
  149. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-mrt/SKILL.md +3 -3
  150. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-scapi-custom/SKILL.md +1 -1
  151. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-scapi-schemas/SKILL.md +1 -1
  152. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-site-import-export/SKILL.md +1 -1
  153. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-sites/SKILL.md +1 -1
  154. package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-slas/SKILL.md +1 -1
  155. package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/.codex-plugin/plugin.json +1 -1
  156. package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/plugin.json +1 -1
  157. package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/skills/b2c-checkout-triage/SKILL.md +2 -2
  158. package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/skills/b2c-job-health/SKILL.md +2 -2
  159. package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/skills/b2c-order-failure-triage/SKILL.md +1 -1
  160. package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/skills/b2c-order-failure-triage/references/order-evidence.md +2 -2
  161. package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/skills/b2c-production-triage/SKILL.md +4 -4
  162. package/node_modules/@salesforce/b2c-agent-plugins/figma-to-sfnext-pagedesigner/README.md +4 -4
  163. package/node_modules/@salesforce/b2c-agent-plugins/figma-to-sfnext-pagedesigner/skills/figma-to-sfnext-pagedesigner/SKILL.md +76 -73
  164. package/node_modules/@salesforce/b2c-agent-plugins/figma-to-sfnext-pagedesigner/skills/figma-to-sfnext-pagedesigner/evals/trigger-evals.json +12 -10
  165. package/node_modules/@salesforce/b2c-agent-plugins/figma-to-sfnext-pagedesigner/skills/figma-to-sfnext-pagedesigner/references/PAGE-DESIGNER-SFN.md +49 -74
  166. package/node_modules/@salesforce/b2c-agent-plugins/package.json +1 -1
  167. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/.codex-plugin/plugin.json +9 -6
  168. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/README.md +43 -22
  169. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/plugin.json +9 -6
  170. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-accessibility/SKILL.md +103 -0
  171. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-accessibility/evals/trigger-evals.json +5 -0
  172. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-accessibility/references/checklist.md +64 -0
  173. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-analytics-consent/SKILL.md +91 -0
  174. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-analytics-consent/evals/trigger-evals.json +5 -0
  175. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-analytics-consent/references/CUSTOM-ADAPTER.md +49 -0
  176. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-authentication/SKILL.md +86 -79
  177. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-authentication/evals/trigger-evals.json +5 -0
  178. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-authentication/references/COOKIES.md +39 -0
  179. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-authentication/references/LOGIN-FLOWS.md +59 -0
  180. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-commerce-features/SKILL.md +67 -0
  181. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-commerce-features/evals/trigger-evals.json +5 -0
  182. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-commerce-features/references/FEATURE-PREREQUISITES.md +37 -0
  183. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/SKILL.md +98 -136
  184. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/evals/trigger-evals.json +5 -0
  185. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/references/COMPONENT-AUTHORING.md +118 -0
  186. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/references/SHAPE-TOKENS.md +51 -0
  187. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/references/STORYBOOK.md +54 -0
  188. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/references/TOKEN-SYSTEM.md +53 -0
  189. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/references/TROUBLESHOOTING.md +19 -0
  190. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-configuration/SKILL.md +116 -113
  191. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-configuration/evals/trigger-evals.json +5 -0
  192. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-configuration/references/ENV-VARIABLES.md +55 -0
  193. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-configuration/references/MULTI-SITE-URLS.md +137 -0
  194. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/SKILL.md +100 -150
  195. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/evals/trigger-evals.json +5 -0
  196. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/references/ACTIONS.md +53 -0
  197. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/references/API-CLIENTS.md +34 -0
  198. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/references/LOADERS.md +73 -0
  199. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/references/SCAPI-FETCHER.md +23 -77
  200. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-deployment/SKILL.md +83 -97
  201. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-deployment/evals/trigger-evals.json +5 -0
  202. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-deployment/references/MRT-DEPLOYMENT.md +37 -68
  203. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/SKILL.md +73 -97
  204. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/evals/trigger-evals.json +5 -0
  205. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/references/ACTION-HOOKS.md +57 -0
  206. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/references/BASE-AUDIT.md +47 -44
  207. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/references/CLI-AND-INSTALL.md +58 -0
  208. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/references/EXTENSION-EXAMPLES.md +49 -86
  209. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-hybrid-storefronts/SKILL.md +59 -114
  210. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-hybrid-storefronts/evals/trigger-evals.json +5 -0
  211. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-hybrid-storefronts/references/HYBRID-PROXY-CONFIG.md +53 -90
  212. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-i18n/SKILL.md +96 -131
  213. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-i18n/evals/trigger-evals.json +5 -0
  214. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-i18n/references/locale-config.md +35 -0
  215. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-overview/SKILL.md +101 -0
  216. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-overview/evals/trigger-evals.json +5 -0
  217. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/SKILL.md +152 -131
  218. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/evals/trigger-evals.json +5 -0
  219. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/references/BUSINESS-MANAGER.md +46 -0
  220. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/references/COMPONENT-REGISTRY.md +86 -53
  221. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/references/DECORATOR-PATTERNS.md +119 -131
  222. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/references/REVIEW-CHECKLIST.md +83 -0
  223. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/references/TROUBLESHOOTING.md +35 -0
  224. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-performance/SKILL.md +75 -105
  225. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-performance/evals/trigger-evals.json +5 -0
  226. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-performance/references/PERFORMANCE-REVIEW-CHECKLIST.md +85 -0
  227. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-performance/references/SUSPENSE-AND-STREAMING.md +58 -0
  228. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/SKILL.md +103 -116
  229. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/evals/trigger-evals.json +5 -0
  230. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/references/PROJECT-STRUCTURE.md +61 -99
  231. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/references/SCRIPTS.md +47 -0
  232. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/references/SFNEXT-CLI.md +63 -0
  233. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-quality-gates/SKILL.md +70 -0
  234. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-quality-gates/evals/trigger-evals.json +5 -0
  235. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-quality-gates/references/lint-and-budgets.md +39 -0
  236. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-revalidation/SKILL.md +121 -0
  237. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-revalidation/evals/trigger-evals.json +5 -0
  238. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-revalidation/references/POLICIES-AND-TAGS.md +55 -0
  239. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-routing/SKILL.md +86 -143
  240. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-routing/evals/trigger-evals.json +5 -0
  241. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-routing/references/ROUTE-CONVENTIONS.md +51 -51
  242. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-routing/references/URLS-AND-SEO-ROUTES.md +22 -0
  243. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi/SKILL.md +126 -0
  244. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi/evals/trigger-evals.json +5 -0
  245. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi/references/WORKED-EXAMPLE.md +39 -0
  246. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-security/SKILL.md +129 -0
  247. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-security/evals/trigger-evals.json +5 -0
  248. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-security/references/COOKIE-DOMAIN.md +39 -0
  249. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-security/references/TURNSTILE.md +43 -0
  250. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-seo/SKILL.md +95 -0
  251. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-seo/evals/trigger-evals.json +5 -0
  252. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-seo/references/MULTI-DOMAIN-BASE-PATH.md +17 -0
  253. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-seo/references/SEO-ROUTES.md +31 -0
  254. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-state-management/SKILL.md +80 -89
  255. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-state-management/evals/trigger-evals.json +5 -0
  256. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-state-management/references/PATTERNS.md +45 -0
  257. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-testing/SKILL.md +105 -138
  258. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-testing/evals/trigger-evals.json +5 -0
  259. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-testing/references/E2E.md +38 -0
  260. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-testing/references/STORYBOOK-PATTERNS.md +73 -94
  261. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-testing/references/UNIT-AND-ROUTE-TESTS.md +60 -0
  262. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-theming/SKILL.md +104 -0
  263. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-theming/evals/trigger-evals.json +5 -0
  264. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-theming/references/REBRAND-CHECKLIST.md +29 -0
  265. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next-figma/skills/sfnext-create-figma-kit/SKILL.md +3 -3
  266. package/oclif.manifest.json +21 -4
  267. package/package.json +3 -3
  268. package/content/guidance/storefront-next/sfnext-create-component/SKILL.md +0 -195
  269. package/content/guidance/storefront-next/sfnext-create-component/references/COMPONENT-AUTHORING.md +0 -206
  270. package/content/guidance/storefront-next/sfnext-create-component/references/PROJECT-STRUCTURE.md +0 -43
  271. package/content/guidance/storefront-next/sfnext-create-component/references/TOKEN-SYSTEM.md +0 -130
  272. package/content/guidance/storefront-next/sfnext-create-component/references/TROUBLESHOOTING.md +0 -34
  273. package/content/guidance/storefront-next/sfnext-create-vertical/SKILL.md +0 -135
  274. package/content/guidance/storefront-next/sfnext-create-vertical/references/COMPONENT-AUTHORING.md +0 -206
  275. package/content/guidance/storefront-next/sfnext-create-vertical/references/PROJECT-STRUCTURE.md +0 -43
  276. package/content/guidance/storefront-next/sfnext-create-vertical/references/TOKEN-SYSTEM.md +0 -130
  277. package/content/guidance/storefront-next/sfnext-create-vertical/references/TROUBLESHOOTING.md +0 -34
  278. package/content/guidance/storefront-next/sfnext-custom-apis/SKILL.md +0 -221
  279. package/content/guidance/storefront-next/sfnext-custom-apis/references/WORKFLOW-EXAMPLES.md +0 -294
  280. package/content/guidance/storefront-next/sfnext-data-fetching/references/LOADER-PATTERNS.md +0 -102
  281. package/content/guidance/storefront-next/sfnext-project-setup/references/ENV-VARIABLES.md +0 -82
  282. package/content/guidance/storefront-next/sfnext-scapi-management/SKILL.md +0 -203
  283. package/content/guidance/storefront-next/sfnext-scapi-management/references/CLI-COMMANDS.md +0 -122
  284. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/SKILL.md +0 -195
  285. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/evals/trigger-evals.json +0 -12
  286. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/references/COMPONENT-AUTHORING.md +0 -206
  287. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/references/PROJECT-STRUCTURE.md +0 -43
  288. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/references/TOKEN-SYSTEM.md +0 -130
  289. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/references/TROUBLESHOOTING.md +0 -34
  290. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/SKILL.md +0 -135
  291. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/evals/trigger-evals.json +0 -12
  292. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/references/COMPONENT-AUTHORING.md +0 -206
  293. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/references/PROJECT-STRUCTURE.md +0 -43
  294. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/references/TOKEN-SYSTEM.md +0 -130
  295. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/references/TROUBLESHOOTING.md +0 -34
  296. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-custom-apis/SKILL.md +0 -221
  297. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-custom-apis/evals/trigger-evals.json +0 -12
  298. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-custom-apis/references/WORKFLOW-EXAMPLES.md +0 -294
  299. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/references/LOADER-PATTERNS.md +0 -102
  300. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/references/ENV-VARIABLES.md +0 -82
  301. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi-management/SKILL.md +0 -203
  302. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi-management/evals/trigger-evals.json +0 -12
  303. package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi-management/references/CLI-COMMANDS.md +0 -122
  304. /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/custom-apis.md +0 -0
  305. /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/custom-properties.md +0 -0
  306. /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/jobs.md +0 -0
  307. /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/products.md +0 -0
  308. /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/promotions.md +0 -0
  309. /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/saving.md +0 -0
  310. /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/snippets.md +0 -0
  311. /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/tokens.md +0 -0
  312. /package/content/guidance/mcp/{server → b2c-mcp-server}/references/files.md +0 -0
@@ -1,180 +1,123 @@
1
1
  ---
2
2
  name: sfnext-routing
3
- description: Implement file-based routing in Storefront Next with React Router 7. Use when adding new pages, creating layout routes, defining route parameters, or understanding route module exports (loader, action, component, meta). Covers flat-routes conventions, nested layouts, and the _app prefix.
3
+ description: >-
4
+ Add and change pages in a Storefront Next project: flat-file routes in src/routes, layout routes (_app, _checkout, _empty), splat routes for product and category pages, action.* and resource.* routes, src/route-paths.ts (routes, resourceRoutes, routeHref), site-aware Link and useNavigate wrappers, SeoMeta and JsonLd head tags, multi-site /:siteId/:localeId URL prefixes, url.seoRoutes and excludeRoutes, extension routes, and the SLAS callback routes. Use for "add a page", "new route", "why is my link missing the site prefix", "route file naming", "redirect to login", or a 404 on a new URL. Do not use for loader/action/fetcher data code (use `storefront-next:sfnext-data-fetching`), shouldRevalidate (use `storefront-next:sfnext-revalidation`), SEO strategy such as sitemaps and canonical rules (use `storefront-next:sfnext-seo`), or Page Designer regions (use `storefront-next:sfnext-page-designer`).
4
5
  ---
5
6
 
6
- # Routing Skill
7
+ # Storefront Next Routing
7
8
 
8
- This skill covers React Router 7 file-based routing in Storefront Next projects.
9
+ Storefront Next uses React Router 7 framework mode with file-based routes. Every route module lives in `src/routes/`; the file name is the URL. Your project also ships `docs/README-MULTI-SITE.md` (URL prefix, locale and site detection) and `docs/README-SEO.md` (titles, meta tags, canonical URLs); read those for depth.
9
10
 
10
- ## Overview
11
+ ## How routes are discovered
11
12
 
12
- Storefront Next uses React Router 7 in framework mode with flat-routes file conventions. Route files live in `src/routes/` and file names map directly to URL paths using dot (`.`) separators for nesting.
13
+ `src/routes.ts` imports `flatRoutes` from `@salesforce/storefront-next-runtime/routing` (not `@react-router/fs-routes`). It is a drop-in wrapper that:
13
14
 
14
- ## Route File Conventions
15
+ 1. scans `src/routes/` (test files are ignored),
16
+ 2. merges routes from `src/extensions/<name>/routes/` (see `storefront-next:sfnext-extensions`),
17
+ 3. wraps every route in the `app.url.prefix` pattern (default `/:siteId/:localeId`) through `src/app-wrapper.tsx`, and applies `app.url.seoRoutes` aliases to the product and category splats.
15
18
 
16
- ### File Name to URL Mapping
19
+ The two SLAS callback routes (`resource.slas-reset-password-callback.ts`, `resource.slas-passwordless-login-callback.ts`) are deliberately excluded from discovery in `src/routes.ts` and registered by hand at the bare paths `/reset-password-callback` and `/passwordless-login-callback`, outside the prefix, so a single callback URL works for all sites. If you add another server-to-server callback that cannot carry a site prefix, follow the same pattern in `src/routes.ts`.
17
20
 
18
- | File Name | URL Path | Notes |
19
- |-----------|----------|-------|
20
- | `_app.tsx` | — | Layout route (wraps child routes) |
21
- | `_app._index.tsx` | `/` | Home page (index of `_app` layout) |
22
- | `_app.product.$productId.tsx` | `/product/:productId` | Dynamic parameter |
23
- | `_app.category.$categoryId.tsx` | `/category/:categoryId` | Dynamic parameter |
24
- | `_app.cart.tsx` | `/cart` | Static route |
25
- | `_app.account.tsx` | `/account` | Layout for account pages |
26
- | `_app.account.orders.tsx` | `/account/orders` | Nested under account layout |
21
+ ## Route tree (what exists)
27
22
 
28
- ### Naming Rules
23
+ | Pattern | Files | Notes |
24
+ |---|---|---|
25
+ | `_app` layout | `_app.tsx` | header/footer shell; loads navigation; `shouldRevalidate` returns `false` |
26
+ | Home, search, cart, wishlist | `_app._index.tsx`, `_app.search.tsx`, `_app.cart.tsx`, `_app.wishlist.tsx`, `_app.about-us.tsx` | |
27
+ | Product detail | `_app.p.$.tsx` | splat; URL shape is build-time configurable (`url.seoRoutes`) |
28
+ | Category / listing | `_app.c.$.tsx` | splat; URL shape is build-time configurable (`url.seoRoutes`) |
29
+ | Account | `_app.account.tsx` (layout + auth guard), `_app.account.overview`, `.orders`, `.orders.$orderNo`, `.addresses`, `.payment-methods`, `.wishlist`, `.passkeys`, `.store-preferences` | |
30
+ | Orders | `_app.order-confirmation.$orderNo.tsx`, `_app.order-lookup.*` (`results.$orderNo`, `verify.$orderNo`) | param is `$orderNo` |
31
+ | `_checkout` layout | `_checkout.tsx`, `_checkout.checkout.tsx` | checkout chrome |
32
+ | `_empty` layout | `_empty.tsx`, `_empty.login`, `.signup`, `.forgot-password`, `.reset-password`, `.logout`, `.maintenance`, `.oauth2.jwks`, `.preview.component`, `_empty.$.tsx` (catch-all) | no header/footer; there is no `_auth` layout |
33
+ | Mutations | `action.*.ts(x)` (cart, wishlist, checkout, OTP, passkey, consent, site context...) | no UI; see `storefront-next:sfnext-data-fetching` |
34
+ | Data endpoints | `resource.*.ts(x)` (recommendations, basket-products, category-products, analytics-proxy, `resource.api.client.$resource.ts`...) | no UI |
29
35
 
30
- - **Dots (`.`)** create path segments: `_app.product.tsx` maps to `/product`
31
- - **`$` prefix** marks dynamic parameters: `$productId` becomes `:productId`
32
- - **`_` prefix** marks layout routes (pathless): `_app.tsx` wraps children without adding a URL segment
33
- - **`_index`** matches the parent path exactly (index route)
36
+ Naming rules (flat routes): `.` becomes `/`, `$name` is a param, `$` alone is a splat, a leading `_` segment is a pathless layout, `_index` is the index route. Pick the layout by prefix: `_app.` for standard pages, `_checkout.` for checkout, `_empty.` for header-less pages.
34
37
 
35
- See [Route Conventions Reference](references/ROUTE-CONVENTIONS.md) for the complete naming rules.
38
+ ## Add a page
36
39
 
37
- ## Route Module Exports
38
-
39
- Each route file can export these values:
40
-
41
- ### loader — Server-side data loading
40
+ ```tsx
41
+ // src/routes/_app.shipping-policy.tsx -> /shipping-policy
42
+ import type { Route } from './+types/_app.shipping-policy';
43
+ import { SeoMeta } from '@/components/seo-meta';
44
+ import { Link } from '@/components/link';
45
+ import { routes } from '@/route-paths';
42
46
 
43
- ```typescript
44
- import { createApiClients } from '@/lib/api-clients';
45
- import type { LoaderFunctionArgs } from 'react-router';
47
+ export async function loader({ request }: Route.LoaderArgs) {
48
+ return { pageUrl: new URL(request.url).href };
49
+ }
46
50
 
47
- export function loader({ params, context }: LoaderFunctionArgs) {
48
- const clients = createApiClients(context);
49
- return {
50
- product: clients.shopperProducts.getProduct({
51
- params: { path: { id: params.productId } }
52
- }).then(({ data }) => data),
53
- };
51
+ export default function ShippingPolicy({ loaderData }: Route.ComponentProps) {
52
+ return (
53
+ <>
54
+ <SeoMeta title="Shipping policy" description="How we ship." openGraph={{ url: loaderData.pageUrl }} />
55
+ <h1>Shipping policy</h1>
56
+ <Link to={routes.cart}>Back to cart</Link>
57
+ </>
58
+ );
54
59
  }
55
60
  ```
56
61
 
57
- ### action — Handle mutations (form submissions)
62
+ Checklist for a new page:
58
63
 
59
- ```typescript
60
- import { data, redirect } from 'react-router';
61
- import type { ActionFunctionArgs } from 'react-router';
64
+ 1. Create the file under `src/routes/` with the right layout prefix.
65
+ 2. Import types from `./+types/<file-name>` (`Route.LoaderArgs`, `Route.ComponentProps`, `Route.ActionArgs`). These are generated by `pnpm typecheck` (runs `react-router typegen`) and `pnpm dev`; run one if the import is unresolved.
66
+ 3. Add an entry to `routes` (page) or `resourceRoutes` (action/resource) in `src/route-paths.ts`. That file is the single source of truth for navigable paths. Keep it in sync when you rename or delete route files.
67
+ 4. Render `<SeoMeta>` (and `<JsonLd>` from `@/components/json-ld` for structured data) inside the component. React 19 hoists these tags to `<head>` and they work with streaming. Use `meta` exports only when a route already does.
68
+ 5. Add locale strings for user-facing text (`storefront-next:sfnext-i18n`) and a test next to the route (`storefront-next:sfnext-testing`).
62
69
 
63
- export async function action({ request, context }: ActionFunctionArgs) {
64
- const formData = await request.formData();
65
- // Handle mutation...
66
- return data({ success: true });
67
- }
70
+ ## Links and navigation: always use the project wrappers
71
+
72
+ ```tsx
73
+ import { Link, NavLink } from '@/components/link';
74
+ import { useNavigate } from '@/hooks/use-navigate';
75
+ import { href } from 'react-router';
76
+ import { routes, routeHref, resourceRoutes } from '@/route-paths';
77
+
78
+ <Link to={routes.cart}>Cart</Link>
79
+ <Link to={routeHref(routes.accountOrderDetail, { orderNo })}>Order</Link>
68
80
  ```
69
81
 
70
- ### default — Page component
82
+ `Link`, `NavLink` and `useNavigate` from `@/components/link` and `@/hooks/use-navigate` apply the site/locale prefix (`buildUrl`). The React Router originals compile but silently produce unprefixed URLs that break multi-site routing. `AGENTS.md` makes this a hard rule.
71
83
 
72
- Components receive `loaderData` as props from the framework:
84
+ For product and category URLs use the helpers in `@/route-paths` (`createProductUrl`, `createCategoryUrl`, `createCategoryNavigationUrl`) with the SEO URL context so links follow `url.seoRoutes`. In server code (redirects), use `buildUrlFromContext(routes.login, context)` from `@/lib/url.server`:
73
85
 
74
- ```typescript
75
- import { Suspense } from 'react';
76
- import { Await } from 'react-router';
77
- import { SeoMeta } from '@/components/seo-meta';
86
+ ```ts
87
+ import { redirect } from 'react-router';
88
+ import { routes } from '@/route-paths';
89
+ import { buildUrlFromContext } from '@/lib/url.server';
78
90
 
79
- export default function CategoryPage({ loaderData }: { loaderData: CategoryPageData }) {
80
- // `category` is already resolved (awaited in loader)
81
- // `products` is a Promise (streamed)
82
- return (
83
- <>
84
- <SeoMeta
85
- title={loaderData.category.name}
86
- description={loaderData.category.pageDescription}
87
- />
88
- <h1>{loaderData.category.name}</h1>
89
- <Suspense fallback={<ProductGridSkeleton />}>
90
- <Await resolve={loaderData.products}>
91
- {(products) => <ProductGrid products={products} />}
92
- </Await>
93
- </Suspense>
94
- </>
95
- );
96
- }
91
+ throw redirect(buildUrlFromContext(routes.login, context));
97
92
  ```
98
93
 
99
- For SEO metadata, use the `<SeoMeta />` component inside your page component (not a `meta` export).
94
+ Form and fetcher `action` targets come from `resourceRoutes` (for example `resourceRoutes.cartItemAdd`), which are excluded from the site prefix via `app.url.excludeRoutes` in `config.server.ts` (`['/resource/**', '/action/**']` by default). A new `action.*` or `resource.*` route needs no prefix handling; a new page route gets it automatically.
100
95
 
101
- ## Layout Routes
96
+ ## URL configuration
102
97
 
103
- Layout routes wrap child routes with shared UI (navigation, footer, etc.):
98
+ `app.url` in `config.server.ts` (`prefix`, `excludeRoutes` and `seoRoutes` are protected config paths: set them in the file and rebuild, they cannot be overridden with `PUBLIC__` env vars; see `storefront-next:sfnext-configuration`) controls `prefix`, `excludeRoutes`, search-param mode, detection and `seoRoutes` (configurable product and category URL grammars). Changing the prefix or `seoRoutes` affects every link; follow `docs/README-MULTI-SITE.md` in your project rather than editing ad hoc.
104
99
 
105
- ```typescript
106
- // src/routes/_app.tsx — Main app layout
107
- import { Outlet } from 'react-router';
100
+ ## Protecting routes
108
101
 
109
- export default function AppLayout() {
110
- return (
111
- <div>
112
- <Header />
113
- <main>
114
- <Outlet /> {/* Child routes render here */}
115
- </main>
116
- <Footer />
117
- </div>
118
- );
119
- }
120
- ```
102
+ There is no `_auth` layout. Guard in the loader: read the session with `getAuth(context)` from `@/middlewares/auth.server` and `throw redirect(...)` to `routes.login` (see `_app.account.tsx` and `_app.wishlist.tsx`). Auth details: `storefront-next:sfnext-authentication`.
121
103
 
122
- ### Adding a New Page
123
-
124
- 1. Create a route file in `src/routes/`:
125
- ```
126
- src/routes/_app.wishlist.tsx → /wishlist
127
- ```
128
-
129
- 2. Export a `loader` for data and `default` for the component:
130
- ```typescript
131
- import { createApiClients } from '@/lib/api-clients';
132
- import { SeoMeta } from '@/components/seo-meta';
133
- import type { LoaderFunctionArgs } from 'react-router';
134
-
135
- type WishlistPageData = {
136
- wishlist: Promise<Wishlist>;
137
- };
138
-
139
- export function loader({ context }: LoaderFunctionArgs): WishlistPageData {
140
- const clients = createApiClients(context);
141
- return {
142
- wishlist: clients.shopperCustomers.getWishlist({...}).then(({ data }) => data),
143
- };
144
- }
145
-
146
- export default function WishlistPage({ loaderData }: { loaderData: WishlistPageData }) {
147
- return (
148
- <>
149
- <SeoMeta title="My Wishlist" />
150
- <Suspense fallback={<WishlistSkeleton />}>
151
- <Await resolve={loaderData.wishlist}>
152
- {(wishlist) => <div>{/* Render wishlist */}</div>}
153
- </Await>
154
- </Suspense>
155
- </>
156
- );
157
- }
158
- ```
159
-
160
- ## Resource Routes
161
-
162
- Routes that return data (no UI component):
163
-
164
- ```typescript
165
- // src/routes/resource.api.client.$resource.tsx
166
- // Used by useScapiFetcher to execute SCAPI calls server-side
167
- export function loader({ params, context }: LoaderFunctionArgs) {
168
- // Decode params, call SCAPI, return JSON
169
- }
170
- ```
104
+ ## Rules to keep in mind
171
105
 
172
- ## Related Skills
106
+ - Only server `loader` and `action` exports are allowed; no `clientLoader`/`clientAction`.
107
+ - Throw `new Response('...', { status: 404 })` for missing content so the right HTTP status reaches crawlers.
108
+ - Resource routes called from the browser should reject cross-origin requests (see `resource.recommendations.ts` for the pattern).
109
+ - Deeper references: [ROUTE-CONVENTIONS.md](references/ROUTE-CONVENTIONS.md) for exports and naming, [URLS-AND-SEO-ROUTES.md](references/URLS-AND-SEO-ROUTES.md) for prefixes and SEO aliases.
110
+
111
+ ## Finding more
173
112
 
174
- - `storefront-next:sfnext-data-fetching` - What happens inside loader and action functions
175
- - `storefront-next:sfnext-components` - Building page components with createPage
176
- - `storefront-next:sfnext-page-designer` - Page Designer routes with regions
113
+ Read `AGENTS.md` in your project for the doc index. For other framework questions use `b2c docs search "storefront next routing"` (or the `docs_search` MCP tool).
177
114
 
178
- ## Reference Documentation
115
+ ## Related Skills
179
116
 
180
- - [Route Conventions Reference](references/ROUTE-CONVENTIONS.md) - Complete naming rules and examples
117
+ - `storefront-next:sfnext-data-fetching` - loaders, actions, fetchers
118
+ - `storefront-next:sfnext-revalidation` - `shouldRevalidate` policy per route
119
+ - `storefront-next:sfnext-seo` - canonical URLs, structured data, sitemaps
120
+ - `storefront-next:sfnext-page-designer` - `@PageType` and regions on routes
121
+ - `storefront-next:sfnext-extensions` - routes contributed by extensions
122
+ - `storefront-next:sfnext-authentication` - sessions and login flows
123
+ - `storefront-next:sfnext-overview` - architecture map
@@ -0,0 +1,5 @@
1
+ [
2
+ {"query": "Add a new /shipping-policy page to my Storefront Next project with the standard header and footer", "should_trigger": true},
3
+ {"query": "My Link to the cart drops the /site/locale prefix in a multi-site storefront, how do I fix navigation?", "should_trigger": true},
4
+ {"query": "How do I stream non-critical data from a loader and avoid blocking the first byte?", "should_trigger": false}
5
+ ]
@@ -1,65 +1,65 @@
1
- # Route Conventions Reference
1
+ # Route conventions
2
2
 
3
- ## Flat Routes File Naming
3
+ ## File name to URL
4
4
 
5
- Storefront Next uses React Router 7's flat-routes convention where dots (`.`) in file names create URL path segments.
5
+ | File | URL (before the site/locale prefix) |
6
+ |---|---|
7
+ | `_app._index.tsx` | `/` |
8
+ | `_app.cart.tsx` | `/cart` |
9
+ | `_app.account.orders.$orderNo.tsx` | `/account/orders/:orderNo` |
10
+ | `_app.p.$.tsx` | product splat (shape set by `url.seoRoutes`; use `createProductUrl`) |
11
+ | `_app.c.$.tsx` | category splat (shape set by `url.seoRoutes`; use `createCategoryUrl`) |
12
+ | `_checkout.checkout.tsx` | `/checkout` |
13
+ | `_empty.login.tsx` | `/login` |
14
+ | `action.cart-item-add.tsx` | `/action/cart-item-add` |
15
+ | `resource.recommendations.ts` | `/resource/recommendations` |
16
+ | `resource.api.client.$resource.ts` | `/resource/api/client/:resource` |
6
17
 
7
- ### Syntax Reference
18
+ - A segment starting with `_` and no matching file content of its own is a pathless layout (`_app`, `_checkout`, `_empty`). The layout file (`_app.tsx`) renders `<Outlet />`.
19
+ - A nested layout is a route file plus children, for example `_app.account.tsx` with `_app.account.overview.tsx` beneath it.
20
+ - `.ts` is enough for routes without JSX (actions, resource routes, `_empty.logout.ts`).
21
+ - Files named `*.test.ts(x)` beside routes are ignored by route discovery.
8
22
 
9
- | Syntax | Purpose | Example File | URL |
10
- |--------|---------|-------------|-----|
11
- | `.` | Path separator | `_app.product.tsx` | `/product` |
12
- | `$param` | Dynamic segment | `_app.product.$id.tsx` | `/product/:id` |
13
- | `_prefix` | Pathless layout | `_app.tsx` | (no URL segment) |
14
- | `_index` | Index route | `_app._index.tsx` | `/` (parent path) |
23
+ ## Route module exports
15
24
 
16
- ### Common Route Patterns
25
+ | Export | Purpose |
26
+ |---|---|
27
+ | `loader` | server data for the route (see `storefront-next:sfnext-data-fetching`) |
28
+ | `action` | server mutation |
29
+ | default component | receives `loaderData` via `Route.ComponentProps` |
30
+ | `shouldRevalidate` | revalidation policy; most routes re-export from `@/lib/revalidation/routes/*` (see `storefront-next:sfnext-revalidation`) |
31
+ | `middleware` | route-level server middleware (root chain lives in `src/root.tsx`) |
32
+ | `ErrorBoundary` | route-scoped error UI (for example wishlist load failures) |
33
+ | `links` / `meta` | mostly used in `src/root.tsx`; prefer `<SeoMeta>` in components |
34
+ | Page Designer classes | `@PageType` and `@RegionDefinition` on an exported class, see `storefront-next:sfnext-page-designer` |
17
35
 
18
- ```
19
- src/routes/
20
- ├── _app.tsx # Layout: wraps all /app routes
21
- ├── _app._index.tsx # /
22
- ├── _app.product.$productId.tsx # /product/:productId
23
- ├── _app.category.$categoryId.tsx # /category/:categoryId
24
- ├── _app.cart.tsx # /cart
25
- ├── _app.checkout.tsx # /checkout
26
- ├── _app.account.tsx # Layout: wraps /account routes
27
- ├── _app.account._index.tsx # /account
28
- ├── _app.account.orders.tsx # /account/orders
29
- ├── _app.account.orders.$orderId.tsx # /account/orders/:orderId
30
- ├── _app.search.tsx # /search
31
- ├── _auth.tsx # Layout: auth pages
32
- ├── _auth.login.tsx # /login
33
- ├── _auth.register.tsx # /register
34
- └── resource.api.client.$resource.tsx # Resource route (no UI)
35
- ```
36
+ `clientLoader` and `clientAction` are not permitted.
36
37
 
37
- ### Layout Nesting
38
+ ## Typed route props
38
39
 
39
- ```
40
- URL: /account/orders/12345
40
+ ```tsx
41
+ import type { Route } from './+types/_app.cart';
41
42
 
42
- Route hierarchy:
43
- _app.tsx (layout — renders Header, Footer, <Outlet />)
44
- _app.account.tsx (layout — renders account sidebar, <Outlet />)
45
- _app.account.orders.$orderId.tsx (page — renders order details)
43
+ export async function loader({ request, context, params }: Route.LoaderArgs) { /* ... */ }
44
+ export default function Cart({ loaderData }: Route.ComponentProps) { /* ... */ }
46
45
  ```
47
46
 
48
- ## Route Module Exports
47
+ The `+types` modules are generated. Run `pnpm typecheck` or `pnpm dev` to create them.
48
+
49
+ ## Layout notes
50
+
51
+ - `_app.tsx` loads navigation categories once and exports `shouldRevalidate() { return false }`, so the header data is not re-fetched on later navigations. Change this only if you add navigation that must update.
52
+ - `_empty.tsx` is a minimal `<main>` with a skip link, used by login, signup, callbacks, maintenance and the component preview.
53
+ - `_checkout.tsx` provides the checkout layout.
54
+ - `_app.account.tsx` is the account layout and redirects unauthenticated shoppers to login.
55
+
56
+ ## Head tags
49
57
 
50
- | Export | Type | When It Runs | Purpose |
51
- |--------|------|-------------|---------|
52
- | `loader` | Function | Server (SSR + SPA navigation) | Load data |
53
- | `action` | Function | Server (form submissions) | Handle mutations |
54
- | `default` | Component | Client + Server | Render UI |
55
- | `meta` | Function | Server | Set page title, description, OG tags |
56
- | `handle` | Object | Client + Server | Attach route metadata |
57
- | `ErrorBoundary` | Component | Client + Server | Error UI for this route |
58
- | `headers` | Function | Server | Set HTTP response headers |
58
+ `SeoMeta` props: `title`, `rawTitle`, `description`, `noIndex`, `siteName`, `twitter`, `openGraph`. Use `noIndex` on account and transactional pages. `JsonLd` takes `data`, optional `id` and `nonce`. Both can be rendered anywhere in the tree, including inside a Suspense boundary.
59
59
 
60
- ## Important Notes
60
+ ## Checklist when renaming or deleting a route
61
61
 
62
- - All loaders run on the server, both during SSR and client-side navigation
63
- - Route files must be `.tsx` (TypeScript with JSX) — JavaScript files are forbidden
64
- - The `_app` prefix is a pathless layout; it does not add `/app` to the URL
65
- - Resource routes (no default export) return data only, no rendered HTML
62
+ 1. Update `src/route-paths.ts`.
63
+ 2. Search for the old path in links, redirects, `resourceRoutes` users and tests.
64
+ 3. Re-run `pnpm typecheck` to regenerate `+types`.
65
+ 4. If the route is referenced by `shouldRevalidate` policies in `src/lib/revalidation/routes/`, update those.
@@ -0,0 +1,22 @@
1
+ # Site prefixes, excluded routes and SEO aliases
2
+
3
+ Configuration lives under `app.url` in `config.server.ts`. Full reference: `docs/README-CONFIG-OPTIONS.md` and `docs/README-MULTI-SITE.md` in your project.
4
+
5
+ | Key | Effect |
6
+ |---|---|
7
+ | `url.prefix` | path pattern wrapped around every page route; default `/:siteId/:localeId` |
8
+ | `url.excludeRoutes` | globs that skip the prefix; default `['/resource/**', '/action/**']` |
9
+ | `url.seoRoutes` | per-site product and category URL grammars (slug segments, category modes, redirects) |
10
+
11
+ ## Rules
12
+
13
+ - Define page paths without the prefix (as in `src/route-paths.ts`). The `Link` wrapper, `useNavigate` and `buildUrlFromContext` add it.
14
+ - Never concatenate `/${siteId}/${locale}` by hand.
15
+ - Keep `_app.p.$.tsx` and `_app.c.$.tsx` as splat routes; `seoRoutes` aliases resolve through them. Do not rename them.
16
+ - Build product and category links with `createProductUrl`, `createCategoryUrl` and `createCategoryNavigationUrl` from `@/route-paths`, passing the SEO URL context (`useSeoUrlContext` in `@/hooks/use-seo-url-context`), so slugs and prefixes stay consistent.
17
+ - A loader that resolves a product or category from the URL should use the resolvers under `@/lib/seo/` (see `_app.p.$.tsx`: `resolveProductRoute` from `@/lib/seo/url-resolution.server`) instead of parsing `params` directly.
18
+ - For SEO URL strategy and Business Manager alignment see `storefront-next:sfnext-seo`.
19
+
20
+ ## Callbacks that cannot carry a prefix
21
+
22
+ SLAS redirects back to a fixed URL. Register such routes by hand in `src/routes.ts`: add the file to `IGNORED_ROUTE_FILES` and append `route('/your-callback', 'routes/your-file.ts')` after `flatRoutes(...)`, exactly as the two existing SLAS callbacks do. Then register the full URL in SLAS (see `storefront-next:sfnext-authentication`).
@@ -0,0 +1,126 @@
1
+ ---
2
+ name: sfnext-scapi
3
+ description: >-
4
+ Use and extend SCAPI clients in a Storefront Next project: createApiClients, the `@/scapi` type barrel, typing `c_*` custom attributes by overriding a built-in client, and adding your own custom API end to end with `b2c sfnext scapi` (add, available, list, remove). Use for "clients.shopperProducts", "c_ attribute is not typed", "sfnext scapi add", "add custom API to the storefront", src/scapi/ generated files, custom-clients.ts, calling a loyalty/notify-style custom endpoint from a loader or action, useScapiFetcher, personalized=none for custom clients, or 404 from a custom endpoint. Do not use for writing the cartridge/schema.yaml itself (use `b2c:b2c-custom-api-development`), endpoint registration status (use `b2c-cli:b2c-scapi-custom`), loader/caching strategy (use `storefront-next:sfnext-data-fetching`), or login/session code (use `storefront-next:sfnext-authentication`).
5
+ ---
6
+
7
+ # Storefront Next SCAPI Clients and Custom APIs
8
+
9
+ The runtime (`@salesforce/storefront-next-runtime/scapi`) already ships typed clients for the standard shopper APIs (products, search, baskets, customers, orders, and so on). You do not "add" those. `sfnext scapi add` does one of two things on top:
10
+
11
+ 1. **Override** a built-in client (client key matches, for example `shopperProducts`) with a richer schema, typically your tenant's schema expanded with `c_*` custom attributes, so `product.c_myAttr` is typed.
12
+ 2. **Add a custom API** you deployed to B2C Commerce (a new property such as `clients.loyalty`).
13
+
14
+ Which one you get is decided automatically from the client key. Deep dive: `docs/README-SCAPI.md` in your project.
15
+
16
+ ## The CLI surface
17
+
18
+ Run as `b2c sfnext scapi ...`, or inside your project as `pnpm sfnext scapi ...` (the `sfnext` bin ships with the project). Add `-d <dir>` / `--project-directory` to target another directory.
19
+
20
+ | Command | What it does |
21
+ |---|---|
22
+ | `scapi available` | Probes your tenant: for each of the built-in shopper APIs counts `c_*` attributes, lists tenant custom APIs, and prints the matching `scapi add` command. Needs OAuth. No filter flags. |
23
+ | `scapi add <apiFamily> <apiName> <apiVersion>` | Pull mode: fetch the schema from the SCAPI Schemas API. Needs OAuth. |
24
+ | `scapi add --schema <file> --name <clientKey>` | Local mode: use a YAML/JSON OpenAPI file. `--name` is required here. |
25
+ | `scapi list` | Shows registered Overrides and Custom APIs (schema, base path, locale). |
26
+ | `scapi remove <clientKey>` | Removes the registration and its generated files (one positional argument: the client key, for example `loyalty`). |
27
+
28
+ `add` flags: `--name <key>` (defaults to camelCase of the API name in pull mode), `--base-path <path>` (derived from the schema `servers[].url` if omitted), `--supports-locale` / `--no-supports-locale` (overrides inherit the built-in default), `--expand-custom-properties` (default on, pull mode only; include `c_*`, use `--no-expand-custom-properties` to skip). Re-running `add` regenerates; there is no `--force` and no `--json`. There is no install step after `add`.
29
+
30
+ **Pull mode prerequisites:** SCAPI short code (`SFCC_SHORTCODE` or `--short-code`), tenant id (`SFCC_TENANT_ID` or `--tenant-id`), and an Account Manager API client allowed the `sfcc.scapi-schemas` scope (`SFCC_CLIENT_ID` and `SFCC_CLIENT_SECRET`, or `--client-id`/`--client-secret`, or `dw.json`). The legacy names `SFCC_OAUTH_CLIENT_ID` / `SFCC_OAUTH_CLIENT_SECRET` are also accepted because the CLI resolves both. If the `@salesforce/storefront-next-dev` package is in the project, `b2c` uses that local version.
31
+
32
+ ```bash
33
+ # Which built-in APIs have c_ attributes on my tenant? Which custom APIs exist?
34
+ b2c sfnext scapi available
35
+
36
+ # Type c_* attributes on products (override; pulls schema with custom properties)
37
+ b2c sfnext scapi add product shopper-products v1
38
+
39
+ # Register a custom API from the tenant, or from a local file
40
+ b2c sfnext scapi add custom loyalty v1
41
+ b2c sfnext scapi add --schema ./loyalty-api.yaml --name loyalty --base-path /custom/loyalty/v1
42
+
43
+ b2c sfnext scapi list
44
+ b2c sfnext scapi remove loyalty
45
+ ```
46
+
47
+ For a schema-only look without touching the project use `b2c scapi schemas get/list` (see `b2c-cli:b2c-scapi-schemas`; both need `--tenant-id`).
48
+
49
+ ## What gets generated
50
+
51
+ ```
52
+ src/scapi/
53
+ index.ts barrel (generated), the only SCAPI import surface for app code
54
+ custom-clients.ts registry of overrides and custom clients (generated)
55
+ schemas/ <name>-<ver>.yaml and .meta.json
56
+ generated/ <name>-<ver>.ts, .operations.ts, (.namespace.ts for overrides)
57
+ ```
58
+
59
+ Never hand-edit these; rerun `sfnext scapi add`. Registry entries carry `key`, `basePath`, `ops`, `locale`, `orgPrefix`. Custom clients use `orgPrefix: true` (base `/custom/<name>/v1/organizations/{orgId}`); the shipped `sfnextNotify` entry is a working example.
60
+
61
+ ## Import rule
62
+
63
+ Import types and clients from the barrel, not from the runtime package:
64
+
65
+ ```typescript
66
+ import { ApiError, type ShopperProducts } from '@/scapi'; // picks up overrides
67
+ // import { ShopperProducts } from '@salesforce/storefront-next-runtime/scapi'; // bypasses overrides, lint warns
68
+ ```
69
+
70
+ Only `src/scapi/**` and `src/lib/api-clients.server.ts` may import the runtime path directly.
71
+
72
+ ## Use clients in loaders and actions
73
+
74
+ ```typescript
75
+ import { createApiClients } from '@/lib/api-clients.server';
76
+
77
+ export async function loader({ context }: LoaderFunctionArgs) {
78
+ const clients = createApiClients(context);
79
+ const { data: product } = await clients.shopperProducts.getProduct({
80
+ params: { path: { id: 'my-product-id' } },
81
+ });
82
+ const { data: rewards } = await clients.loyalty.getLoyaltyRewards(); // custom client
83
+ return { product, rewardTier: product?.c_loyaltyTier, rewards };
84
+ }
85
+ ```
86
+
87
+ - Calls return `{ data }` and **throw** `ApiError` on failure (wrap in `NormalizedApiError` from `@/lib/api/normalized-api-error` when you need a message/status).
88
+ - `createApiClients` automatically injects `organizationId`, `siteId` and (when the client supports it) `locale`. Do not pass `siteId` yourself.
89
+ - Auth comes from the shopper token in the auth middleware (`storefront-next:sfnext-authentication`); do not read tokens to call SCAPI manually. Get the shopper via `getAuth(context)` only when you need `customerId`.
90
+ - Prefer the existing helpers in `src/lib/api/*.server.ts` (search, products, basket, wishlist, order) for standard APIs, and put your own custom-API calls in a new `src/lib/api/<thing>.server.ts`.
91
+ - Calling from the browser: `useScapiFetcher(client, method, options)` goes through `/resource/api/client/...`, which only allows a short **allow-list** of operations (`src/lib/scapi/resource-policy.ts`), and `siteId`/`locale`/`organizationId` are server-owned. A new custom operation is not callable from the browser until you add it there; prefer a route loader/action. The `'helpers'` overload is deprecated. See `docs/README-PERFORMANCE.md` and `docs/README-REVALIDATION.md` for fetcher lifecycle rules.
92
+
93
+ ## End-to-end: a new custom API
94
+
95
+ 1. **Author the endpoint** (cartridge `rest-apis/<api-name>/` with `api.json`, `schema.yaml`, script) using `b2c:b2c-custom-api-development`. `api.json` maps `endpoint` to `schema` and `implementation`; auth is declared in `schema.yaml` (`ShopperToken` for storefront calls, with a `c_` scope under `security:`). The shipped `cartridges/app_storefrontnext_base/cartridge/rest-apis/sfnext-notify/` is a complete example.
96
+ 2. **Deploy and activate**: `b2c code deploy <cartridge> --reload` (reload toggles activation so endpoints re-register; see `b2c-cli:b2c-code`).
97
+ 3. **Confirm registration**: `b2c scapi custom status --tenant-id <id>` (filter with `--status not_registered`). Use `b2c-cli:b2c-scapi-custom` for 404s and `errorReason`.
98
+ 4. **Allow the scope**: add the custom scope to the SLAS client used by the storefront (`b2c-cli:b2c-slas`). The shopper token must carry it, otherwise calls get 401/403.
99
+ 5. **Register in the storefront**: `b2c sfnext scapi add custom <api-name> v1` (or `--schema` with a local copy).
100
+ 6. **Call it** from a server loader/action as above; `import type` request/response types from `@/scapi`.
101
+ 7. After schema changes repeat steps 2 and 5.
102
+
103
+ ## Non-personalized caching
104
+
105
+ Storefront Next can add `personalized=none` to eligible GET requests through one central policy. Overrides and custom clients are **left unclassified** until you review and approve their exact transports in the policy module. Do not loosen it to `() => true`. See `docs/README-SCAPI-NON-PERSONALIZED-RESPONSES.md` before approving a client.
106
+
107
+ ## Pitfalls
108
+
109
+ - Expecting `scapi add shopper-search ...` to be needed: standard clients already exist.
110
+ - Importing from `@salesforce/storefront-next-runtime/scapi` and wondering why `c_*` is untyped.
111
+ - Forgetting `--reload` after deploy, so the endpoint stays unregistered (404).
112
+ - Passing `siteId` or `locale` in `params.query`: server-owned, stripped on the resource route and injected elsewhere.
113
+ - Override key typos: the key must exactly match a built-in (`shopperProducts`, `shopperBasketsV2`, ...) or you create an unrelated custom client.
114
+ - Custom client used from the browser fetcher without allow-listing it.
115
+
116
+ Worked example of a shipped custom API: [references/WORKED-EXAMPLE.md](references/WORKED-EXAMPLE.md).
117
+
118
+ ## Related Skills
119
+
120
+ - `b2c:b2c-custom-api-development` - author the cartridge, api.json, schema.yaml, scripts
121
+ - `b2c-cli:b2c-scapi-custom` - registration status and debugging 404s
122
+ - `b2c-cli:b2c-scapi-schemas` - browse SCAPI schemas
123
+ - `b2c-cli:b2c-slas` - add custom scopes to the SLAS client
124
+ - `storefront-next:sfnext-data-fetching` - loaders, actions, caching
125
+ - `storefront-next:sfnext-authentication` - `getAuth`, sessions
126
+ - `storefront-next:sfnext-revalidation` - fetcher revalidation rules
@@ -0,0 +1,5 @@
1
+ [
2
+ {"query": "My product.c_brandStory custom attribute shows up as unknown in TypeScript on the PDP. How do I get it typed in Storefront Next?", "should_trigger": true},
3
+ {"query": "I deployed a loyalty custom API to my sandbox. How do I register it in the storefront with sfnext scapi and call it from a route loader?", "should_trigger": true},
4
+ {"query": "How do I write the schema.yaml and api.json for a new custom API endpoint in my cartridge?", "should_trigger": false}
5
+ ]
@@ -0,0 +1,39 @@
1
+ # Worked Example: the shipped `sfnext-notify` custom API
2
+
3
+ Your project already contains one complete custom API, used to send login and password-reset emails. Copy its shape for your own.
4
+
5
+ | Piece | Location in your project |
6
+ |---|---|
7
+ | Endpoint mapping | `cartridges/app_storefrontnext_base/cartridge/rest-apis/sfnext-notify/api.json` |
8
+ | Contract and auth | `.../sfnext-notify/schema.yaml` (`ShopperToken` security scheme, scope `c_sfnext_notify`, `security:` on the operation) |
9
+ | Implementation | `.../sfnext-notify/Notify.js` (exports `notify`, matching `"implementation": "Notify"` and the `operationId`) |
10
+ | Storefront registration | `src/scapi/schemas/sfnext-notify-v1.yaml` + `.meta.json`, `src/scapi/generated/`, entry in `src/scapi/custom-clients.ts` |
11
+ | Server call site | `src/lib/notify/notify.server.ts` |
12
+
13
+ `api.json` maps each `operationId` to a schema file and script module:
14
+
15
+ ```json
16
+ { "endpoints": [ { "endpoint": "notify", "schema": "schema.yaml", "implementation": "Notify" } ] }
17
+ ```
18
+
19
+ Registry entry generated by `sfnext scapi add`:
20
+
21
+ ```typescript
22
+ { key: 'sfnextNotify', basePath: '/custom/sfnext-notify/v1', ops: ops0, locale: true, orgPrefix: true }
23
+ ```
24
+
25
+ Call site (server only):
26
+
27
+ ```typescript
28
+ import { createApiClients } from '@/lib/api-clients.server';
29
+
30
+ const clients = createApiClients(context);
31
+ await clients.sfnextNotify.notify({ params: {}, body }); // siteId, organizationId injected
32
+ ```
33
+
34
+ Notes:
35
+
36
+ - Authentication is enforced by the SCAPI gateway (shopper token must carry `c_sfnext_notify`), not in the script. Register the scope on the SLAS client once with `sfnext setup-base-cartridge --slas-client-id <id>`.
37
+ - `sfnextNotify` is intentionally **not** in the browser resource-route allow-list, so it cannot be invoked from `useScapiFetcher`; a test in the project asserts this.
38
+ - Being a custom client, it is left unclassified by the non-personalized-response policy, which is correct for a POST.
39
+ - To follow the pattern for your own API: write the cartridge (`b2c:b2c-custom-api-development`), `b2c code deploy <cartridge> --reload`, verify with `b2c scapi custom status --tenant-id <id>`, then `b2c sfnext scapi add custom <name> v1`.