Skip to main content

b2c-page-designer

Define Page Designer page types and component types with regions, attributes, and rendering scripts. Use this skill whenever the user needs to create a new page or component type, configure regions with allowed component constraints, define attribute_definition_groups, debug why a component does not appear in the editor, or fix enum/color attribute pitfalls. Also use when building visual merchandising experiences -- even if they just say 'my component is missing from PD' or 'add a hero banner component'.

来源信息

仓库
SalesforceCommerceCloud/b2c-developer-tooling
最近来源活动
2026年7月31日 13:36
检测到的 SKILL.md 语言
英语
星标
54
分支
21

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
4 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
b2c-page-designer
description
Define Page Designer page types and component types with regions, attributes, and rendering scripts. Use this skill whenever the user needs to create a new page or component type, configure regions with allowed component constraints, define attribute_definition_groups, debug why a component does not appear in the editor, or fix enum/color attribute pitfalls. Also use when building visual merchandising experiences -- even if they just say 'my component is missing from PD' or 'add a hero banner component'.
# Page Designer Skill This skill guides you through creating custom Page Designer page types and component types for Salesforce B2C Commerce. ## Scope & grounding This skill covers B2C Commerce Page Designer (dw.experience package) with version-agnostic patterns, JSON schema structures, and code examples. JSON schemas and Script API signatures shown are illustrative and may drift across platform versions. Before answering questions that name a framework/version, or before emitting code the user will run, confirm against the docs via `docs_search`/`docs_read` (MCP) or `b2c docs search`/`b2c docs read` (CLI). The B2C Commerce documentation is the canonical grounding source for Script API methods, attribute schema requirements, and version-specific behaviors not covered here. **Canonical docs:** - `dw.experience.PageMgr` - rendering pages and regions - `dw.experience.PageScriptContext` - page script context API - `dw.experience.ComponentScriptContext` - component script context API - `dw.experience.Page` - page object methods - `dw.experience.Component` - component object methods - `dw.experience.Region` - region object methods - `dw.experience.image.Image` - image attribute type - `dw.experience` - package overview ## Overview Page Designer allows merchants to create and manage content pages through a visual editor. Developers create: 1. **Page Types** - Define page structures with regions 2. **Component Types** - Reusable content blocks with configurable attributes ## File Structure Page Designer files are in the cartridge's `experience` directory: ``` /my-cartridge /cartridge /experience /pages homepage.json # Page type meta definition homepage.js # Page type script /components banner.json # Component type meta definition banner.js # Component type script /templates /default /experience /pages homepage.isml # Page template /components banner.isml # Component template ``` **Naming:** The `.json` and `.js` files must have matching names. Use only **alphanumeric** or **underscore** in file names and in any subdirectory names under `experience/pages` or `experience/components`. **Component types in subfolders:** You can put component meta and script in a subdirectory (e.g. `experience/components/assets/`). The **component type ID** is then the path with dots: `assets.hero_image_block`. The template path under `templates/default/` must mirror that path (e.g. `templates/default/experience/components/assets/hero_image_block.isml`), and the script must call `Template('experience/components/assets/hero_image_block')` so the path matches. Stored ID is `component.{component_type_id}`; total length must not exceed 256 characters. ## Page Types ### Meta Definition (pages/homepage.json) > Illustrative JSON schema; confirm version-specific page type schema requirements with official platform documentation. ```json { "name": "Home Page", "description": "Landing page with hero and content regions", "region_definitions": [ { "id": "hero", "name": "Hero Section", "max_components": 1 }, { "id": "content", "name": "Main Content" }, { "id": "footer", "name": "Footer Section", "component_type_exclusions": [ { "type_id": "video" } ] } ] } ``` ### Page Script (pages/homepage.js) ```javascript 'use strict'; var Template = require('dw/util/Template'); var HashMap = require('dw/util/HashMap'); var PageRenderHelper = require('*/cartridge/experience/utilities/PageRenderHelper.js'); module.exports.render = function (context) { var model = new HashMap(); var page = context.page; model.page = page; model.regions = PageRenderHelper.getRegionModelRegistry(page); return new Template('experience/pages/homepage').render(model).text; }; ``` ### Page Template (templates/default/experience/pages/homepage.isml) > This follows SFRA's region-model pattern: the page script builds `pdict.regions` with > `PageRenderHelper.getRegionModelRegistry(page)`, and each `RegionModel.render()` call delegates to > the platform's `PageMgr.renderRegion()` with SFRA's render settings. ```html <isdecorate template="common/layout/page"> <div class="homepage"> <div class="hero-region"> <isprint value="${pdict.regions.hero.render()}" encoding="off"/> </div> <div class="content-region"> <isprint value="${pdict.regions.content.render()}" encoding="off"/> </div> <div class="footer-region"> <isprint value="${pdict.regions.footer.render()}" encoding="off"/> </div> </div> </isdecorate> ``` ## Component Types ### Meta Definition (components/banner.json) > Illustrative JSON schema; confirm version-specific component type schema requirements with official platform documentation. ```json { "name": "Banner", "description": "Promotional banner with image and CTA", "group": "content", "region_definitions": [], "attribute_definition_groups": [ { "id": "image", "name": "Image Settings", "attribute_definitions": [ { "id": "image", "name": "Banner Image", "type": "image", "required": true }, { "id": "alt", "name": "Alt Text", "type": "string", "required": true } ] }, { "id": "content", "name": "Content", "attribute_definitions": [ { "id": "headline", "name": "Headline", "type": "string", "required": true }, { "id": "body", "name": "Body Text", "type": "markup" }, { "id": "ctaUrl", "name": "CTA Link", "type": "url" }, { "id": "ctaText", "name": "CTA Button Text", "type": "string" } ] }, { "id": "layout", "name": "Layout Options", "attribute_definitions": [ { "id": "alignment", "name": "Text Alignment", "type": "enum", "values": ["left", "center", "right"], "default_value": "center" }, { "id": "fullWidth", "name": "Full Width", "type": "boolean", "default_value": false } ] } ] } ``` **Component meta:** Always include `region_definitions`. Use `[]` when the component has no nested regions (no slots for other components). ### Component Script (components/banner.js) ```javascript 'use strict'; var Template = require('dw/util/Template'); var HashMap = require('dw/util/HashMap'); var URLUtils = require('dw/web/URLUtils'); module.exports.render = function (context) { var model = new HashMap(); var content = context.content; // Access merchant-configured attributes model.put('image', content.image); // Image object model.put('alt', content.alt); // String model.put('headline', content.headline); // String model.put('body', content.body); // Markup string model.put('ctaUrl', content.ctaUrl); // URL object model.put('ctaText', content.ctaText); // String model.put('alignment', content.alignment || 'center'); model.put('fullWidth', content.fullWidth); return new Template('experience/components/banner').render(model).text; }; ``` **Template path:** The path passed to `Template(...)` must match the template path under `templates/default/`. If the component lives in a subfolder (e.g. `experience/components/assets/hero_image_block`), use `Template('experience/components/assets/hero_image_block')` and place the ISML at `templates/default/experience/components/assets/hero_image_block.isml`. **Handling colors (string or color picker object):** If an attribute can be a hex string or a color picker object `{ color: "#hex" }`, use a small helper so the script works with both: ```javascript function getColor(colorAttr) { if (!colorAttr) return ''; if (typeof colorAttr === 'string' && colorAttr.trim()) return colorAttr.trim(); if (colorAttr.color) return colorAttr.color; return ''; } ``` ### Component Template (templates/experience/components/banner.isml) ```html <div class="banner ${pdict.fullWidth ? 'banner--full-width' : ''}" style="text-align: ${pdict.alignment}"> <isif condition="${pdict.image}"> <img src="${pdict.image.file.absURL}" alt="${pdict.alt}" class="banner__image"/> </isif> <div class="banner__content"> <h2 class="banner__headline">${pdict.headline}</h2> <isif condition="${pdict.body}"> <div class="banner__body"> <isprint value="${pdict.body}" encoding="off"/> </div> </isif> <isif condition="${pdict.ctaUrl && pdict.ctaText}"> <a href="${pdict.ctaUrl}" class="banner__cta btn btn-primary"> ${pdict.ctaText} </a> </isif> </div> </div> ``` ## Attribute Types > Illustrative attribute schema; confirm version-specific attribute_definition syntax with official platform documentation. | Type | Description | Returns | |------|-------------|---------| | `string` | Text input | String | | `text` | Multi-line text | String | | `markup` | Rich text editor | Markup string (use `encoding="off"`) | | `boolean` | Checkbox | Boolean | | `integer` | Number input | Integer | | `enum` | Single select dropdown | String or integer (depends on values) | | `image` | Image picker | Image object with `file.absURL` | | `file` | File picker | File object | | `url` | URL picker | URL string | | `category` | Category selector | Category object | | `product` | Product selector | Product object | | `page` | Page selector | Page object | | `custom` | JSON object or custom editor | Object (or editor-specific) | **Enum — critical for component visibility:** Use a **string array** for `values`: `"values": ["left", "center", "right"]`. Do **not** use objects like `{ "value": "x", "display_value": "X" }`; that format can cause the component type to be rejected and **not appear** in the Page Designer component list. Enum attributes return string when values are strings, integer when values are numeric. **Custom and colors:** `type: "custom"` with e.g. `editor_definition.type: "styling.colorPicker"` requires a cartridge that provides that editor on the **Business Manager** site cartridge path. If the component does not show up in the editor, use `type: "string"` for color attributes (merchant types a hex). In the script, support both: accept a string or an object like `{ color: "#hex" }` (e.g. a small `getColor(attr)` helper that returns the string). **default_value:** Used for storefront rendering only; it is **not** shown as preselected in the Page Designer visual editor. ## Region Definitions ```json { "region_definitions": [ { "id": "main", "name": "Main Content", "max_components": 10, "component_type_exclusions": [ { "type_id": "heavy-component" } ], "component_type_inclusions": [ { "type_id": "text-block" }, { "type_id": "image-block" } ] } ] } ``` | Property | Description |
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看