dist/codex/salesforce-commerce/skills/js-modern/SKILL.md
Write modern JavaScript and TypeScript — ES6+ features, async/await, modules, destructuring, optional chaining, TypeScript types. Covers SFCC server-side JS (CommonJS, limited ES6), PWA Kit (full modern JS/TS), and LWC JavaScript (Lightning Locker constraints). Use when writing JavaScript for Salesforce Commerce.
npx skillsauth add orcaqubits/agentic-commerce-claude-plugins js-modernInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Write modern JavaScript and TypeScript for Salesforce Commerce platforms.
Always fetch the latest official documentation BEFORE writing JavaScript:
This ensures you're using the latest syntax, APIs, and best practices for each platform.
This is the most critical concept. Three Salesforce Commerce platforms have fundamentally different JavaScript runtimes:
| Constraint | SFCC Server-Side | PWA Kit | LWC (B2B) |
|-----------|-----------------|---------|------------|
| Engine | Rhino (Java-based) | Node.js + V8 | Browser (V8/SpiderMonkey) |
| Module system | CommonJS (require) | ES Modules (import) | ES Modules (import) |
| async/await | Not supported | Fully supported | Fully supported |
| Promises | Not supported | Fully supported | Fully supported |
| Template literals | Limited contexts | Fully supported | Fully supported |
| Arrow functions | Supported | Supported | Supported |
| Destructuring | Supported | Supported | Supported |
| Optional chaining | Not supported | Supported | Supported |
| Classes | Not supported | Supported | Required (extends LightningElement) |
| Decorators | Not applicable | Not applicable | Required (@api, @track, @wire) |
| DOM access | Not applicable | Standard DOM | Shadow DOM only (Locker/LWS) |
The Rhino engine imposes strict limitations. Every SFCC script must account for these:
var or let/const (recent versions) -- verify against your instanceasync/await, no Promise -- all I/O is synchronousrequire('dw/...') and module.exportsdw.* namespace (e.g., dw/catalog/ProductMgr)module.superModule for cartridge overlay inheritance// Pattern: SFCC module import
var ProductMgr = require('dw/catalog/ProductMgr');
// Fetch live docs for dw.* API signatures
// Pattern: module.superModule extension
var base = module.superModule;
// Fetch live docs for superModule behavior
Full modern JavaScript and TypeScript are available:
| Feature | Stack |
|---------|-------|
| React | 17+ with hooks |
| TypeScript | Full support, recommended |
| Node.js SSR | Server-side rendering |
| Commerce SDK | commerce-sdk-isomorphic |
| Bundler | Webpack with code splitting |
// Pattern: PWA Kit component with Commerce SDK
// Fetch live docs for useProducts hook API
import { useProducts } from '@salesforce/commerce-sdk-react';
LWC uses modern ES modules but enforces security boundaries:
| Allowed | Not Allowed |
|---------|-------------|
| ES modules (import/export) | Direct window/document manipulation |
| async/await, Promises | eval(), Function() constructor |
| Template literals, destructuring | Third-party DOM libraries (jQuery) |
| @api, @track, @wire decorators | setTimeout(string) |
| this.template.querySelector() | document.getElementById() |
| NavigationMixin | window.location = ... |
// Pattern: LWC component skeleton
// Fetch live docs for decorator behavior
import { LightningElement, api, wire } from 'lwc';
| System | Syntax | Platform |
|--------|--------|----------|
| CommonJS | require() / module.exports | SFCC server-side |
| ES Modules | import / export | PWA Kit, LWC |
| SFCC Overlay | module.superModule | SFCC cartridge extension |
| SFCC Wildcard | require('*/cartridge/...') | Cross-cartridge resolution |
dw.* APIconst by default, let when reassignment is needed, never var (except SFCC if required)map, filter, reduce) over imperative loops?.) and nullish coalescing (??) where supportedPartial<T>, Pick<T>, Omit<T> for flexible type definitionsFetch MDN, TypeScript handbook, and platform-specific Salesforce docs for exact syntax support and API signatures before implementing.
development
Build with Spree's headless Next.js storefront — the official `spree/storefront` repo (Next.js 16 App Router with Server Actions and Turbopack, React 19 Server Components, Tailwind CSS 4, TypeScript 5, `@spree/sdk`, Sentry), server-only auth (httpOnly JWT cookies + publishable key), MeiliSearch faceted catalog, one-page checkout with Apple/Google Pay/Klarna/Affirm/SEPA, multi-region market routing, GA4 + JSON-LD SEO, and Vercel/Docker deployment. Use when forking or customizing the storefront, or evaluating headless adoption.
tools
Build Spree extensions as Rails engines — gem scaffolding, `bin/rails g spree:extension`, mounting routes/migrations/assets, the modern `prepend` decorator pattern (`*_decorator.rb` with `self.prepended(base)`), generators (`spree:model_decorator`, `spree:controller_decorator`), the four customization surfaces in preference order (Events > Webhooks > Dependencies > Decorators), Spree::Dependencies for swapping service objects, gem release/versioning, and the deprecated Deface engine. Use when building a reusable Spree extension or adding non-trivial customization to an app.
development
Build with Spree's event bus and Webhooks 2.0 — `Spree::Events` publication, `Spree::Subscriber` DSL with `subscribes_to` and `on`, wildcard matching, lifecycle events (`{model}.created/.updated/.deleted` via `publishes_lifecycle_events`), the canonical event catalog (order.*, payment.*, shipment.*, product.*), Webhooks 2.0 endpoints, HMAC-SHA256 signing (`X-Spree-Webhook-Signature`), exponential-backoff retries, and Sidekiq job orchestration. Use when wiring event-driven business logic, building webhook consumers, or replacing ActiveSupport callback chains.
tools
Cross-cutting Spree development patterns — the customization preference hierarchy (Events > Webhooks > Dependencies > Decorators), `Spree::Dependencies` service-object swapping, the `_decorator.rb` + `prepend` + `self.prepended` idiom, idempotent subscribers and webhook receivers, multi-store scoping discipline, prefixed IDs, calculator polymorphism (shipping/promotion/tax share the base), service-object composition with `dry-monads` or simple results, why to avoid `class_eval` reopening and Deface, and Spree-on-Rails idioms (Hotwire/Turbo Stimulus, ActiveStorage, Action Cable, Sidekiq). Use when designing the architecture of a Spree extension or solving cross-cutting concerns.