@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.
- package/bin/run.js +5 -9
- package/content/guidance/b2c/b2c-hooks/references/ORDER-HOOK-LIFECYCLE.md +1 -1
- package/content/guidance/b2c/b2c-onboarding/SKILL.md +4 -4
- package/content/guidance/b2c/b2c-ordering/SKILL.md +2 -2
- package/content/guidance/b2c/b2c-querying-data/SKILL.md +2 -2
- package/content/guidance/b2c/b2c-scapi-admin/SKILL.md +3 -3
- package/content/guidance/b2c/b2c-scapi-admin/references/CLIENT-EXAMPLES.md +4 -4
- package/content/guidance/b2c/b2c-scapi-shopper/SKILL.md +6 -6
- package/content/guidance/b2c/b2c-scapi-shopper/references/CLIENT-EXAMPLES.md +8 -9
- package/content/guidance/b2c-cli/b2c-cip/SKILL.md +3 -3
- package/content/guidance/b2c-cli/b2c-cip/references/SALES_ANALYSIS.md +1 -1
- package/content/guidance/b2c-cli/b2c-config/SKILL.md +31 -21
- package/content/guidance/b2c-cli/b2c-content/SKILL.md +1 -1
- package/content/guidance/b2c-cli/b2c-debug/SKILL.md +1 -1
- package/content/guidance/b2c-cli/b2c-docs/SKILL.md +23 -2
- package/content/guidance/b2c-cli/b2c-ecdn/references/ADVANCED.md +1 -1
- package/content/guidance/b2c-cli/b2c-job/references/IMPORT.md +1 -1
- package/content/guidance/b2c-cli/b2c-metrics/SKILL.md +1 -1
- package/content/guidance/b2c-cli/b2c-mrt/SKILL.md +3 -3
- package/content/guidance/b2c-cli/b2c-scapi-custom/SKILL.md +1 -1
- package/content/guidance/b2c-cli/b2c-scapi-schemas/SKILL.md +1 -1
- package/content/guidance/b2c-cli/b2c-site-import-export/SKILL.md +1 -1
- package/content/guidance/b2c-cli/b2c-sites/SKILL.md +1 -1
- package/content/guidance/b2c-cli/b2c-slas/SKILL.md +1 -1
- package/content/guidance/b2c-ops/b2c-checkout-triage/SKILL.md +2 -2
- package/content/guidance/b2c-ops/b2c-job-health/SKILL.md +2 -2
- package/content/guidance/b2c-ops/b2c-order-failure-triage/SKILL.md +1 -1
- package/content/guidance/b2c-ops/b2c-order-failure-triage/references/order-evidence.md +2 -2
- package/content/guidance/b2c-ops/b2c-production-triage/SKILL.md +4 -4
- package/content/guidance/index.json +935 -258
- package/content/guidance/mcp/{cip → b2c-mcp-cip}/SKILL.md +10 -8
- package/content/guidance/mcp/{b2c-config → b2c-mcp-config}/SKILL.md +10 -9
- package/content/guidance/mcp/{debugger → b2c-mcp-debugger}/SKILL.md +9 -8
- package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/SKILL.md +81 -10
- package/content/guidance/mcp/{server → b2c-mcp-server}/SKILL.md +49 -25
- package/content/guidance/storefront-next/sfnext-accessibility/SKILL.md +103 -0
- package/content/guidance/storefront-next/sfnext-accessibility/references/checklist.md +64 -0
- package/content/guidance/storefront-next/sfnext-analytics-consent/SKILL.md +91 -0
- package/content/guidance/storefront-next/sfnext-analytics-consent/references/CUSTOM-ADAPTER.md +49 -0
- package/content/guidance/storefront-next/sfnext-authentication/SKILL.md +86 -79
- package/content/guidance/storefront-next/sfnext-authentication/references/COOKIES.md +39 -0
- package/content/guidance/storefront-next/sfnext-authentication/references/LOGIN-FLOWS.md +59 -0
- package/content/guidance/storefront-next/sfnext-commerce-features/SKILL.md +67 -0
- package/content/guidance/storefront-next/sfnext-commerce-features/references/FEATURE-PREREQUISITES.md +37 -0
- package/content/guidance/storefront-next/sfnext-components/SKILL.md +98 -136
- package/content/guidance/storefront-next/sfnext-components/references/COMPONENT-AUTHORING.md +118 -0
- package/content/guidance/storefront-next/sfnext-components/references/SHAPE-TOKENS.md +51 -0
- package/content/guidance/storefront-next/sfnext-components/references/STORYBOOK.md +54 -0
- package/content/guidance/storefront-next/sfnext-components/references/TOKEN-SYSTEM.md +53 -0
- package/content/guidance/storefront-next/sfnext-components/references/TROUBLESHOOTING.md +19 -0
- package/content/guidance/storefront-next/sfnext-configuration/SKILL.md +116 -113
- package/content/guidance/storefront-next/sfnext-configuration/references/ENV-VARIABLES.md +55 -0
- package/content/guidance/storefront-next/sfnext-configuration/references/MULTI-SITE-URLS.md +137 -0
- package/content/guidance/storefront-next/sfnext-data-fetching/SKILL.md +100 -150
- package/content/guidance/storefront-next/sfnext-data-fetching/references/ACTIONS.md +53 -0
- package/content/guidance/storefront-next/sfnext-data-fetching/references/API-CLIENTS.md +34 -0
- package/content/guidance/storefront-next/sfnext-data-fetching/references/LOADERS.md +73 -0
- package/content/guidance/storefront-next/sfnext-data-fetching/references/SCAPI-FETCHER.md +23 -77
- package/content/guidance/storefront-next/sfnext-deployment/SKILL.md +83 -97
- package/content/guidance/storefront-next/sfnext-deployment/references/MRT-DEPLOYMENT.md +37 -68
- package/content/guidance/storefront-next/sfnext-extensions/SKILL.md +73 -97
- package/content/guidance/storefront-next/sfnext-extensions/references/ACTION-HOOKS.md +57 -0
- package/content/guidance/storefront-next/sfnext-extensions/references/BASE-AUDIT.md +47 -44
- package/content/guidance/storefront-next/sfnext-extensions/references/CLI-AND-INSTALL.md +58 -0
- package/content/guidance/storefront-next/sfnext-extensions/references/EXTENSION-EXAMPLES.md +49 -86
- package/content/guidance/storefront-next/sfnext-hybrid-storefronts/SKILL.md +59 -114
- package/content/guidance/storefront-next/sfnext-hybrid-storefronts/references/HYBRID-PROXY-CONFIG.md +53 -90
- package/content/guidance/storefront-next/sfnext-i18n/SKILL.md +96 -131
- package/content/guidance/storefront-next/sfnext-i18n/references/locale-config.md +35 -0
- package/content/guidance/storefront-next/sfnext-overview/SKILL.md +101 -0
- package/content/guidance/storefront-next/sfnext-page-designer/SKILL.md +152 -131
- package/content/guidance/storefront-next/sfnext-page-designer/references/BUSINESS-MANAGER.md +46 -0
- package/content/guidance/storefront-next/sfnext-page-designer/references/COMPONENT-REGISTRY.md +86 -53
- package/content/guidance/storefront-next/sfnext-page-designer/references/DECORATOR-PATTERNS.md +119 -131
- package/content/guidance/storefront-next/sfnext-page-designer/references/REVIEW-CHECKLIST.md +83 -0
- package/content/guidance/storefront-next/sfnext-page-designer/references/TROUBLESHOOTING.md +35 -0
- package/content/guidance/storefront-next/sfnext-performance/SKILL.md +75 -105
- package/content/guidance/storefront-next/sfnext-performance/references/PERFORMANCE-REVIEW-CHECKLIST.md +85 -0
- package/content/guidance/storefront-next/sfnext-performance/references/SUSPENSE-AND-STREAMING.md +58 -0
- package/content/guidance/storefront-next/sfnext-project-setup/SKILL.md +103 -116
- package/content/guidance/storefront-next/sfnext-project-setup/references/PROJECT-STRUCTURE.md +61 -99
- package/content/guidance/storefront-next/sfnext-project-setup/references/SCRIPTS.md +47 -0
- package/content/guidance/storefront-next/sfnext-project-setup/references/SFNEXT-CLI.md +63 -0
- package/content/guidance/storefront-next/sfnext-quality-gates/SKILL.md +70 -0
- package/content/guidance/storefront-next/sfnext-quality-gates/references/lint-and-budgets.md +39 -0
- package/content/guidance/storefront-next/sfnext-revalidation/SKILL.md +121 -0
- package/content/guidance/storefront-next/sfnext-revalidation/references/POLICIES-AND-TAGS.md +55 -0
- package/content/guidance/storefront-next/sfnext-routing/SKILL.md +86 -143
- package/content/guidance/storefront-next/sfnext-routing/references/ROUTE-CONVENTIONS.md +51 -51
- package/content/guidance/storefront-next/sfnext-routing/references/URLS-AND-SEO-ROUTES.md +22 -0
- package/content/guidance/storefront-next/sfnext-scapi/SKILL.md +126 -0
- package/content/guidance/storefront-next/sfnext-scapi/references/WORKED-EXAMPLE.md +39 -0
- package/content/guidance/storefront-next/sfnext-security/SKILL.md +129 -0
- package/content/guidance/storefront-next/sfnext-security/references/COOKIE-DOMAIN.md +39 -0
- package/content/guidance/storefront-next/sfnext-security/references/TURNSTILE.md +43 -0
- package/content/guidance/storefront-next/sfnext-seo/SKILL.md +95 -0
- package/content/guidance/storefront-next/sfnext-seo/references/MULTI-DOMAIN-BASE-PATH.md +17 -0
- package/content/guidance/storefront-next/sfnext-seo/references/SEO-ROUTES.md +31 -0
- package/content/guidance/storefront-next/sfnext-state-management/SKILL.md +80 -89
- package/content/guidance/storefront-next/sfnext-state-management/references/PATTERNS.md +45 -0
- package/content/guidance/storefront-next/sfnext-testing/SKILL.md +105 -138
- package/content/guidance/storefront-next/sfnext-testing/references/E2E.md +38 -0
- package/content/guidance/storefront-next/sfnext-testing/references/STORYBOOK-PATTERNS.md +73 -94
- package/content/guidance/storefront-next/sfnext-testing/references/UNIT-AND-ROUTE-TESTS.md +60 -0
- package/content/guidance/storefront-next/sfnext-theming/SKILL.md +104 -0
- package/content/guidance/storefront-next/sfnext-theming/references/REBRAND-CHECKLIST.md +29 -0
- package/dist/commands/mcp.d.ts +8 -2
- package/dist/commands/mcp.js +54 -20
- package/dist/guidance.d.ts +4 -1
- package/dist/guidance.js +23 -5
- package/dist/registry.d.ts +2 -1
- package/dist/registry.js +3 -3
- package/dist/server.d.ts +10 -0
- package/dist/server.js +21 -0
- package/dist/skill-references.js +5 -5
- package/dist/tools/cartridges/index.js +1 -0
- package/dist/tools/cip/index.js +6 -3
- package/dist/tools/diagnostics/debug-capture-at-breakpoint.js +1 -1
- package/dist/tools/diagnostics/debug-set-breakpoints.js +1 -1
- package/dist/tools/diagnostics/debug-start-session.js +1 -1
- package/dist/tools/scapi/index.d.ts +4 -1
- package/dist/tools/scapi/index.js +4 -2
- package/dist/tools/scapi/scapi-code.d.ts +2 -2
- package/dist/tools/scapi/scapi-code.js +17 -61
- package/dist/utils/types.d.ts +6 -0
- package/node_modules/@salesforce/b2c-agent-plugins/CHANGELOG.md +20 -0
- package/node_modules/@salesforce/b2c-agent-plugins/README.md +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/b2c/.codex-plugin/plugin.json +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c/plugin.json +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-hooks/references/ORDER-HOOK-LIFECYCLE.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-onboarding/SKILL.md +4 -4
- package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-ordering/SKILL.md +2 -2
- package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-querying-data/SKILL.md +2 -2
- package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-scapi-admin/SKILL.md +3 -3
- package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-scapi-admin/references/CLIENT-EXAMPLES.md +4 -4
- package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-scapi-shopper/SKILL.md +6 -6
- package/node_modules/@salesforce/b2c-agent-plugins/b2c/skills/b2c-scapi-shopper/references/CLIENT-EXAMPLES.md +8 -9
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/.codex-plugin/plugin.json +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/plugin.json +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-cip/SKILL.md +3 -3
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-cip/references/SALES_ANALYSIS.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-config/SKILL.md +31 -21
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-content/SKILL.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-debug/SKILL.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-docs/SKILL.md +23 -2
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-ecdn/references/ADVANCED.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-job/references/IMPORT.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-metrics/SKILL.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-mrt/SKILL.md +3 -3
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-scapi-custom/SKILL.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-scapi-schemas/SKILL.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-site-import-export/SKILL.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-sites/SKILL.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-cli/skills/b2c-slas/SKILL.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/.codex-plugin/plugin.json +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/plugin.json +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/skills/b2c-checkout-triage/SKILL.md +2 -2
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/skills/b2c-job-health/SKILL.md +2 -2
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/skills/b2c-order-failure-triage/SKILL.md +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/skills/b2c-order-failure-triage/references/order-evidence.md +2 -2
- package/node_modules/@salesforce/b2c-agent-plugins/b2c-ops/skills/b2c-production-triage/SKILL.md +4 -4
- package/node_modules/@salesforce/b2c-agent-plugins/figma-to-sfnext-pagedesigner/README.md +4 -4
- package/node_modules/@salesforce/b2c-agent-plugins/figma-to-sfnext-pagedesigner/skills/figma-to-sfnext-pagedesigner/SKILL.md +76 -73
- package/node_modules/@salesforce/b2c-agent-plugins/figma-to-sfnext-pagedesigner/skills/figma-to-sfnext-pagedesigner/evals/trigger-evals.json +12 -10
- package/node_modules/@salesforce/b2c-agent-plugins/figma-to-sfnext-pagedesigner/skills/figma-to-sfnext-pagedesigner/references/PAGE-DESIGNER-SFN.md +49 -74
- package/node_modules/@salesforce/b2c-agent-plugins/package.json +1 -1
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/.codex-plugin/plugin.json +9 -6
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/README.md +43 -22
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/plugin.json +9 -6
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-accessibility/SKILL.md +103 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-accessibility/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-accessibility/references/checklist.md +64 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-analytics-consent/SKILL.md +91 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-analytics-consent/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-analytics-consent/references/CUSTOM-ADAPTER.md +49 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-authentication/SKILL.md +86 -79
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-authentication/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-authentication/references/COOKIES.md +39 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-authentication/references/LOGIN-FLOWS.md +59 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-commerce-features/SKILL.md +67 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-commerce-features/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-commerce-features/references/FEATURE-PREREQUISITES.md +37 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/SKILL.md +98 -136
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/references/COMPONENT-AUTHORING.md +118 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/references/SHAPE-TOKENS.md +51 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/references/STORYBOOK.md +54 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/references/TOKEN-SYSTEM.md +53 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-components/references/TROUBLESHOOTING.md +19 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-configuration/SKILL.md +116 -113
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-configuration/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-configuration/references/ENV-VARIABLES.md +55 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-configuration/references/MULTI-SITE-URLS.md +137 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/SKILL.md +100 -150
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/references/ACTIONS.md +53 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/references/API-CLIENTS.md +34 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/references/LOADERS.md +73 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/references/SCAPI-FETCHER.md +23 -77
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-deployment/SKILL.md +83 -97
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-deployment/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-deployment/references/MRT-DEPLOYMENT.md +37 -68
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/SKILL.md +73 -97
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/references/ACTION-HOOKS.md +57 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/references/BASE-AUDIT.md +47 -44
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/references/CLI-AND-INSTALL.md +58 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-extensions/references/EXTENSION-EXAMPLES.md +49 -86
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-hybrid-storefronts/SKILL.md +59 -114
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-hybrid-storefronts/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-hybrid-storefronts/references/HYBRID-PROXY-CONFIG.md +53 -90
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-i18n/SKILL.md +96 -131
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-i18n/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-i18n/references/locale-config.md +35 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-overview/SKILL.md +101 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-overview/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/SKILL.md +152 -131
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/references/BUSINESS-MANAGER.md +46 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/references/COMPONENT-REGISTRY.md +86 -53
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/references/DECORATOR-PATTERNS.md +119 -131
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/references/REVIEW-CHECKLIST.md +83 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-page-designer/references/TROUBLESHOOTING.md +35 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-performance/SKILL.md +75 -105
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-performance/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-performance/references/PERFORMANCE-REVIEW-CHECKLIST.md +85 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-performance/references/SUSPENSE-AND-STREAMING.md +58 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/SKILL.md +103 -116
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/references/PROJECT-STRUCTURE.md +61 -99
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/references/SCRIPTS.md +47 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/references/SFNEXT-CLI.md +63 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-quality-gates/SKILL.md +70 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-quality-gates/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-quality-gates/references/lint-and-budgets.md +39 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-revalidation/SKILL.md +121 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-revalidation/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-revalidation/references/POLICIES-AND-TAGS.md +55 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-routing/SKILL.md +86 -143
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-routing/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-routing/references/ROUTE-CONVENTIONS.md +51 -51
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-routing/references/URLS-AND-SEO-ROUTES.md +22 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi/SKILL.md +126 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi/references/WORKED-EXAMPLE.md +39 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-security/SKILL.md +129 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-security/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-security/references/COOKIE-DOMAIN.md +39 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-security/references/TURNSTILE.md +43 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-seo/SKILL.md +95 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-seo/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-seo/references/MULTI-DOMAIN-BASE-PATH.md +17 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-seo/references/SEO-ROUTES.md +31 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-state-management/SKILL.md +80 -89
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-state-management/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-state-management/references/PATTERNS.md +45 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-testing/SKILL.md +105 -138
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-testing/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-testing/references/E2E.md +38 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-testing/references/STORYBOOK-PATTERNS.md +73 -94
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-testing/references/UNIT-AND-ROUTE-TESTS.md +60 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-theming/SKILL.md +104 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-theming/evals/trigger-evals.json +5 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-theming/references/REBRAND-CHECKLIST.md +29 -0
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next-figma/skills/sfnext-create-figma-kit/SKILL.md +3 -3
- package/oclif.manifest.json +21 -4
- package/package.json +3 -3
- package/content/guidance/storefront-next/sfnext-create-component/SKILL.md +0 -195
- package/content/guidance/storefront-next/sfnext-create-component/references/COMPONENT-AUTHORING.md +0 -206
- package/content/guidance/storefront-next/sfnext-create-component/references/PROJECT-STRUCTURE.md +0 -43
- package/content/guidance/storefront-next/sfnext-create-component/references/TOKEN-SYSTEM.md +0 -130
- package/content/guidance/storefront-next/sfnext-create-component/references/TROUBLESHOOTING.md +0 -34
- package/content/guidance/storefront-next/sfnext-create-vertical/SKILL.md +0 -135
- package/content/guidance/storefront-next/sfnext-create-vertical/references/COMPONENT-AUTHORING.md +0 -206
- package/content/guidance/storefront-next/sfnext-create-vertical/references/PROJECT-STRUCTURE.md +0 -43
- package/content/guidance/storefront-next/sfnext-create-vertical/references/TOKEN-SYSTEM.md +0 -130
- package/content/guidance/storefront-next/sfnext-create-vertical/references/TROUBLESHOOTING.md +0 -34
- package/content/guidance/storefront-next/sfnext-custom-apis/SKILL.md +0 -221
- package/content/guidance/storefront-next/sfnext-custom-apis/references/WORKFLOW-EXAMPLES.md +0 -294
- package/content/guidance/storefront-next/sfnext-data-fetching/references/LOADER-PATTERNS.md +0 -102
- package/content/guidance/storefront-next/sfnext-project-setup/references/ENV-VARIABLES.md +0 -82
- package/content/guidance/storefront-next/sfnext-scapi-management/SKILL.md +0 -203
- package/content/guidance/storefront-next/sfnext-scapi-management/references/CLI-COMMANDS.md +0 -122
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/SKILL.md +0 -195
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/evals/trigger-evals.json +0 -12
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/references/COMPONENT-AUTHORING.md +0 -206
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/references/PROJECT-STRUCTURE.md +0 -43
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/references/TOKEN-SYSTEM.md +0 -130
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-component/references/TROUBLESHOOTING.md +0 -34
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/SKILL.md +0 -135
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/evals/trigger-evals.json +0 -12
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/references/COMPONENT-AUTHORING.md +0 -206
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/references/PROJECT-STRUCTURE.md +0 -43
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/references/TOKEN-SYSTEM.md +0 -130
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-create-vertical/references/TROUBLESHOOTING.md +0 -34
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-custom-apis/SKILL.md +0 -221
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-custom-apis/evals/trigger-evals.json +0 -12
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-custom-apis/references/WORKFLOW-EXAMPLES.md +0 -294
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-data-fetching/references/LOADER-PATTERNS.md +0 -102
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-project-setup/references/ENV-VARIABLES.md +0 -82
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi-management/SKILL.md +0 -203
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi-management/evals/trigger-evals.json +0 -12
- package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi-management/references/CLI-COMMANDS.md +0 -122
- /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/custom-apis.md +0 -0
- /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/custom-properties.md +0 -0
- /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/jobs.md +0 -0
- /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/products.md +0 -0
- /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/promotions.md +0 -0
- /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/saving.md +0 -0
- /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/snippets.md +0 -0
- /package/content/guidance/mcp/{scapi → b2c-mcp-scapi}/references/tokens.md +0 -0
- /package/content/guidance/mcp/{server → b2c-mcp-server}/references/files.md +0 -0
package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-routing/SKILL.md
CHANGED
|
@@ -1,180 +1,123 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sfnext-routing
|
|
3
|
-
description:
|
|
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
|
|
7
|
+
# Storefront Next Routing
|
|
7
8
|
|
|
8
|
-
|
|
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
|
-
##
|
|
11
|
+
## How routes are discovered
|
|
11
12
|
|
|
12
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
38
|
+
## Add a page
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
export async function loader({ request }: Route.LoaderArgs) {
|
|
48
|
+
return { pageUrl: new URL(request.url).href };
|
|
49
|
+
}
|
|
46
50
|
|
|
47
|
-
export function
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
62
|
+
Checklist for a new page:
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
```
|
|
75
|
-
import {
|
|
76
|
-
import {
|
|
77
|
-
import {
|
|
86
|
+
```ts
|
|
87
|
+
import { redirect } from 'react-router';
|
|
88
|
+
import { routes } from '@/route-paths';
|
|
89
|
+
import { buildUrlFromContext } from '@/lib/url.server';
|
|
78
90
|
|
|
79
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
96
|
+
## URL configuration
|
|
102
97
|
|
|
103
|
-
|
|
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
|
-
|
|
106
|
-
// src/routes/_app.tsx — Main app layout
|
|
107
|
-
import { Outlet } from 'react-router';
|
|
100
|
+
## Protecting routes
|
|
108
101
|
|
|
109
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
115
|
+
## Related Skills
|
|
179
116
|
|
|
180
|
-
-
|
|
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
|
|
1
|
+
# Route conventions
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## File name to URL
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
38
|
+
## Typed route props
|
|
38
39
|
|
|
39
|
-
```
|
|
40
|
-
|
|
40
|
+
```tsx
|
|
41
|
+
import type { Route } from './+types/_app.cart';
|
|
41
42
|
|
|
42
|
-
Route
|
|
43
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
60
|
+
## Checklist when renaming or deleting a route
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
-
|
|
65
|
-
|
|
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`).
|
package/node_modules/@salesforce/b2c-agent-plugins/storefront-next/skills/sfnext-scapi/SKILL.md
ADDED
|
@@ -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`.
|