From salesforce-commerce
Builds SFRA controllers for Salesforce B2C Commerce: server.get/post/use routes, middleware chains (append/prepend/replace), CSRF protection, form validation, rendering, and caching. Use for request handling.
npx claudepluginhub orcaqubits/agentic-commerce-skills-plugins --plugin salesforce-commerceThis skill is limited to using the following tools:
Build SFRA controllers for request handling in Salesforce B2C Commerce Cloud.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Guides MCP server integration in Claude Code plugins via .mcp.json or plugin.json configs for stdio, SSE, HTTP types, enabling external services as tools.
Build SFRA controllers for request handling in Salesforce B2C Commerce Cloud.
Fetch live documentation FIRST:
Web-search for:
Web-fetch official sources:
github.com/SalesforceCommerceCloud/storefront-reference-architecture (SFRA controllers)Verify before coding: current server module syntax, middleware chain methods, CSRF validation requirements, form validation patterns in latest SFRA.
Controllers are route handlers defined using the server module. Routes follow the naming convention ControllerName-ActionName (e.g., Product-Show, Cart-AddProduct).
controllers/Product.jsProduct-Showhttps://site.com/Product-Show?pid=12345Every controller file ends with module.exports = server.exports();
| Method | HTTP | Purpose | Example |
|---|---|---|---|
server.get(name, ...mw, handler) | GET | Display pages | Product-Show, Cart-Show |
server.post(name, ...mw, handler) | POST | Form submissions | Cart-AddProduct, Account-Register |
server.use(name, ...mw, handler) | Any | Shared logic, API endpoints | Method-agnostic handlers |
Middleware functions execute left to right before the final handler. Each must call next() to continue the chain.
server.post('Action',
server.middleware.https, -> 1. Force HTTPS
csrfProtection.validateRequest, -> 2. Validate CSRF
userLoggedIn.validateLoggedIn, -> 3. Require login
function (req, res, next) {} -> 4. Handler
);
Common built-in middleware:
server.middleware.https -- force HTTPScsrfProtection.validateRequest -- CSRF token validationcsrfProtection.generateToken -- generate CSRF token for formsuserLoggedIn.validateLoggedIn -- require authenticated userconsentTracking.consent -- consent tracking check| Method | What Happens | When to Use |
|---|---|---|
server.extend(base) | Inherit all base routes | Always start with this |
server.append('Route', fn) | Run AFTER base handler | Add data to response, logging, analytics |
server.prepend('Route', fn) | Run BEFORE base handler | Validation, guards, tracking |
server.replace('Route', fn) | Completely override base | Fundamentally different logic (rare) |
server.get/post('Route', fn) | Define new route | New functionality not in base |
// Pattern: Extend a base controller
var base = module.superModule;
server.extend(base);
// Fetch live docs for append/prepend behavior
HTTP Request
-> Route resolution (cartridge path, left-to-right)
-> server.use middleware (guards, validation)
-> server.prepend extensions
-> Base route handler (if extended)
-> server.append extensions
-> Response (render / json / redirect)
| Method | Use Case |
|---|---|
res.render(template, data) | Render ISML template (HTML page) |
res.json(object) | Return JSON (AJAX responses) |
res.redirect(url) | HTTP redirect |
res.setStatusCode(code) | Set HTTP status (404, 500, etc.) |
res.setViewData(data) | Set data for middleware chain sharing |
res.getViewData() | Get data set by previous middleware |
Cache GET responses via property assignment on res:
| Property | Type | Values |
|---|---|---|
res.cachePeriod | Number | Duration value (e.g., 24) |
res.cachePeriodUnit | String | 'minutes', 'hours', 'days' |
Never cache: cart, checkout, account pages. Always cache: product pages, category pages.
All state-changing requests (POST, DELETE) must validate CSRF tokens. The token is generated in the controller, passed to the ISML template as a hidden form field, and validated on submission via csrfProtection.validateRequest middleware.
Server-side form validation uses server.forms.getForm('formName'). Form definitions live in forms/default/*.xml. Always validate server-side -- never trust client-side validation alone.
Product-Show (view), Cart-AddProduct (action)server.use for method-specific routesscripts/ helpersnext() -- forgetting breaks the chain silentlyscripts/middleware/server.middleware.https for all sensitive operations{ success: boolean, data?: object, errors?: array }res.setViewData / res.getViewData to share data across middleware chainreq.querystring, req.form)Transaction.wrap()dw/system/LoggerFetch the SFRA GitHub repository and server module API reference for exact method signatures, middleware patterns, and req/res property details before implementing.