wix-cli-site-plugin
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWix Site Plugin Builder
Wix 站点插件构建工具
Creates site plugin extensions for Wix CLI applications. Site plugins are custom elements that integrate into predefined slots within Wix business solutions (like Wix Stores, Wix Bookings), extending their functionality and user experience.
Site owners can place site plugins into UI slots using the plugin explorer in Wix editors.
为Wix CLI应用创建站点插件扩展。站点插件是可集成到Wix商业解决方案(如Wix Stores、Wix Bookings)中预定义插槽的自定义元素,用于扩展其功能和用户体验。
站点所有者可通过Wix编辑器中的插件资源管理器将站点插件放置到UI插槽中。
Quick Start Checklist
快速入门清单
Follow these steps in order when creating a site plugin:
- Create plugin folder:
src/extensions/site/plugins/<plugin-name>/ - Create extending
<plugin>.tsxwithHTMLElementobservedAttributes - Create with WDS components and
<plugin>.panel.tsxwidget.getProp/setProp - Create with
<plugin>.extension.tsand unique UUIDextensions.sitePlugin() - Update to import and use the new extension
src/extensions.ts - Run to verify TypeScript compiles
npx tsc --noEmit - Run and
npx wix buildto testnpx wix preview - Verify plugin appears in plugin explorer for target slots
创建站点插件时,请按以下顺序执行步骤:
- 创建插件文件夹:
src/extensions/site/plugins/<plugin-name>/ - 创建继承并包含
HTMLElement的observedAttributes文件<plugin>.tsx - 创建包含WDS组件和的
widget.getProp/setProp文件<plugin>.panel.tsx - 创建包含和唯一UUID的
extensions.sitePlugin()文件<plugin>.extension.ts - 更新以导入并使用新扩展
src/extensions.ts - 运行验证TypeScript编译通过
npx tsc --noEmit - 运行和
npx wix build进行测试npx wix preview - 验证插件在目标插槽的插件资源管理器中显示
Architecture
架构
Site plugins consist of three required files:
站点插件包含三个必填文件:
1. Plugin Component (<plugin-name>.tsx
)
<plugin-name>.tsx1. 插件组件(<plugin-name>.tsx
)
<plugin-name>.tsxCustom element component that renders in the slot using native HTMLElement:
- Extend class
HTMLElement - Define for reactive properties
observedAttributes - Implement and
connectedCallback()for renderingattributeChangedCallback() - Use inline styles via template strings
- Attributes use kebab-case (e.g., )
display-name
在插槽中渲染的自定义元素组件,基于原生HTMLElement:
- 继承类
HTMLElement - 定义以声明响应式属性
observedAttributes - 实现和
connectedCallback()用于渲染attributeChangedCallback() - 通过模板字符串使用内联样式
- 属性采用短横线命名法(如)
display-name
2. Settings Panel (<plugin-name>.panel.tsx
)
<plugin-name>.panel.tsx2. 设置面板(<plugin-name>.panel.tsx
)
<plugin-name>.panel.tsxSettings panel shown in the Wix Editor sidebar:
- Uses Wix Design System components (see WDS-COMPONENTS.md)
- Manages plugin properties via widget API
@wix/editor - Loads initial values with
widget.getProp('kebab-case-name') - Updates properties with
widget.setProp('kebab-case-name', value) - Wrapped in
WixDesignSystemProvider > SidePanel > SidePanel.Content
在Wix编辑器侧边栏显示的设置面板:
- 使用Wix设计系统组件(详见WDS-COMPONENTS.md)
- 通过widget API管理插件属性
@wix/editor - 使用加载初始值
widget.getProp('kebab-case-name') - 使用更新属性
widget.setProp('kebab-case-name', value) - 包裹在中
WixDesignSystemProvider > SidePanel > SidePanel.Content
3. Extension Configuration (<plugin-name>.extension.ts
)
<plugin-name>.extension.ts3. 扩展配置(<plugin-name>.extension.ts
)
<plugin-name>.extension.tsDefines the plugin's placement configuration:
- Specifies which slots the plugin can be added to
- Configures auto-add behavior on app installation
- Sets the tag name and file paths
定义插件的放置配置:
- 指定插件可添加到的插槽
- 配置应用安装时的自动添加行为
- 设置标签名称和文件路径
Plugin Component Pattern
插件组件模式
Site plugins use native custom elements:
HTMLElementtypescript
// my-site-plugin.tsx
class MyElement extends HTMLElement {
static get observedAttributes() {
return ['display-name'];
}
constructor() {
super();
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
render() {
const displayName = this.getAttribute('display-name') || "Your Plugin's Title";
this.innerHTML = `
<div style="font-size: 16px; padding: 16px; border: 1px solid #ccc; border-radius: 8px; margin: 16px;">
<h2>${displayName}</h2>
<hr />
<p>
This is a Site Plugin generated by Wix CLI.<br />
Edit your element's code to change this text.
</p>
</div>
`;
}
}
export default MyElement;Key Points:
- Extend class directly
HTMLElement - Define static getter to list reactive attributes
observedAttributes - Attributes use kebab-case (e.g., ,
display-name)bg-color - Implement for initial render
connectedCallback() - Implement to re-render when attributes change
attributeChangedCallback() - Use inline styles via template strings
- Use to read attribute values
this.getAttribute('attribute-name')
站点插件使用原生自定义元素:
HTMLElementtypescript
// my-site-plugin.tsx
class MyElement extends HTMLElement {
static get observedAttributes() {
return ['display-name'];
}
constructor() {
super();
}
connectedCallback() {
this.render();
}
attributeChangedCallback() {
this.render();
}
render() {
const displayName = this.getAttribute('display-name') || "Your Plugin's Title";
this.innerHTML = `
<div style="font-size: 16px; padding: 16px; border: 1px solid #ccc; border-radius: 8px; margin: 16px;">
<h2>${displayName}</h2>
<hr />
<p>
This is a Site Plugin generated by Wix CLI.<br />
Edit your element's code to change this text.
</p>
</div>
`;
}
}
export default MyElement;关键点:
- 直接继承类
HTMLElement - 定义静态getter以列出响应式属性
observedAttributes - 属性采用短横线命名法(如、
display-name)bg-color - 实现用于初始渲染
connectedCallback() - 实现以便属性变化时重新渲染
attributeChangedCallback() - 通过模板字符串使用内联样式
- 使用读取属性值
this.getAttribute('attribute-name')
Settings Panel Pattern
设置面板模式
typescript
// my-site-plugin.panel.tsx
import React, { type FC, useState, useEffect, useCallback } from 'react';
import { widget } from '@wix/editor';
import {
SidePanel,
WixDesignSystemProvider,
Input,
FormField,
} from '@wix/design-system';
import '@wix/design-system/styles.global.css';
const Panel: FC = () => {
const [displayName, setDisplayName] = useState<string>('');
useEffect(() => {
widget.getProp('display-name')
.then(displayName => setDisplayName(displayName || "Your Plugin's Title"))
.catch(error => console.error('Failed to fetch display-name:', error));
}, [setDisplayName]);
const handleDisplayNameChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
const newDisplayName = event.target.value;
setDisplayName(newDisplayName);
widget.setProp('display-name', newDisplayName);
}, [setDisplayName]);
return (
<WixDesignSystemProvider>
<SidePanel width="300" height="100vh">
<SidePanel.Content noPadding stretchVertically>
<SidePanel.Field>
<FormField label="Display Name">
<Input
type="text"
value={displayName}
onChange={handleDisplayNameChange}
aria-label="Display Name"
/>
</FormField>
</SidePanel.Field>
</SidePanel.Content>
</SidePanel>
</WixDesignSystemProvider>
);
};
export default Panel;Key Points:
- Prop names in and
widget.getProp()use kebab-case (e.g.,widget.setProp())"display-name" - Always update both local state AND widget prop in onChange handlers
- Wrap content in
WixDesignSystemProvider > SidePanel > SidePanel.Content - Use WDS components from
@wix/design-system - Import for styles
@wix/design-system/styles.global.css - Include for accessibility
aria-label
typescript
// my-site-plugin.panel.tsx
import React, { type FC, useState, useEffect, useCallback } from 'react';
import { widget } from '@wix/editor';
import {
SidePanel,
WixDesignSystemProvider,
Input,
FormField,
} from '@wix/design-system';
import '@wix/design-system/styles.global.css';
const Panel: FC = () => {
const [displayName, setDisplayName] = useState<string>('');
useEffect(() => {
widget.getProp('display-name')
.then(displayName => setDisplayName(displayName || "Your Plugin's Title"))
.catch(error => console.error('Failed to fetch display-name:', error));
}, [setDisplayName]);
const handleDisplayNameChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
const newDisplayName = event.target.value;
setDisplayName(newDisplayName);
widget.setProp('display-name', newDisplayName);
}, [setDisplayName]);
return (
<WixDesignSystemProvider>
<SidePanel width="300" height="100vh">
<SidePanel.Content noPadding stretchVertically>
<SidePanel.Field>
<FormField label="Display Name">
<Input
type="text"
value={displayName}
onChange={handleDisplayNameChange}
aria-label="Display Name"
/>
</FormField>
</SidePanel.Field>
</SidePanel.Content>
</SidePanel>
</WixDesignSystemProvider>
);
};
export default Panel;关键点:
- 和
widget.getProp()中的属性名称采用短横线命名法(如widget.setProp())"display-name" - 在onChange处理程序中始终同时更新本地状态和widget属性
- 将内容包裹在中
WixDesignSystemProvider > SidePanel > SidePanel.Content - 使用中的WDS组件
@wix/design-system - 导入以应用样式
@wix/design-system/styles.global.css - 包含以满足无障碍要求
aria-label
Attribute Naming Convention
属性命名规范
Site plugins use kebab-case consistently for HTML attributes:
| File | Convention | Example |
|---|---|---|
| kebab-case | |
| kebab-case | |
| kebab-case | |
站点插件的HTML属性统一采用短横线命名法:
| 文件 | 命名规范 | 示例 |
|---|---|---|
| 短横线命名法 | |
| 短横线命名法 | |
| 短横线命名法 | |
Output Structure
输出结构
Site plugins live under . Each plugin has its own folder with files named after the plugin.
src/extensions/site/pluginssrc/extensions/site/plugins/
└── {plugin-name}/
├── {plugin-name}.tsx # Main plugin component (HTMLElement)
├── {plugin-name}.panel.tsx # Settings panel component
└── {plugin-name}.extension.ts # Extension registration
public/
└── {plugin-name}-logo.svg # Plugin logo (optional)站点插件位于目录下。每个插件拥有独立文件夹,文件名称与插件名称一致。
src/extensions/site/pluginssrc/extensions/site/plugins/
└── {plugin-name}/
├── {plugin-name}.tsx # 主插件组件(HTMLElement)
├── {plugin-name}.panel.tsx # 设置面板组件
└── {plugin-name}.extension.ts # 扩展注册文件
public/
└── {plugin-name}-logo.svg # 插件图标(可选)References
参考资料
| Topic | Reference |
|---|---|
| Complete Examples | EXAMPLES.md |
| Slots (App IDs, multiple placements, finding slots) | SLOTS.md |
| WDS Components | WDS-COMPONENTS.md |
| 主题 | 参考链接 |
|---|---|
| 完整示例 | EXAMPLES.md |
| 插槽(应用ID、多位置部署、查找插槽) | SLOTS.md |
| WDS组件 | WDS-COMPONENTS.md |
Available Slots
可用插槽
Site plugins integrate into predefined slots in Wix business solutions. Each slot is identified by:
- appDefinitionId: The ID of the Wix app (e.g., Stores, Bookings)
- widgetId: The ID of the page containing the slot
- slotId: The specific slot identifier
Common placement areas include product pages (Wix Stores), booking pages (Wix Bookings), service pages, and event pages.
For supported pages, common Wix App IDs, and how to find slot IDs, see SLOTS.md.
站点插件可集成到Wix商业解决方案中的预定义插槽中。每个插槽通过以下标识区分:
- appDefinitionId:Wix应用的ID(如Stores、Bookings)
- widgetId:包含插槽的页面ID
- slotId:具体插槽的标识符
常见放置区域包括产品页面(Wix Stores)、预订页面(Wix Bookings)、服务页面和活动页面。
如需了解支持的页面、常见Wix应用ID以及如何查找插槽ID,请查看SLOTS.md。
Extension Registration
扩展注册
Extension registration is MANDATORY and has TWO required steps.
扩展注册是强制性的,包含两个必填步骤。
Step 1: Create Plugin-Specific Extension File
步骤1:创建插件专属扩展文件
Each site plugin requires an extension file in its folder:
typescript
// my-site-plugin.extension.ts
import { extensions } from '@wix/astro/builders';
export default extensions.sitePlugin({
id: '{{GENERATE_UUID}}',
name: 'My Site Plugin',
marketData: {
name: 'My Site Plugin',
description: 'Marketing Description',
logoUrl: '{{BASE_URL}}/my-site-plugin-logo.svg',
},
placements: [{
appDefinitionId: 'a0c68605-c2e7-4c8d-9ea1-767f9770e087',
widgetId: '6a25b678-53ec-4b37-a190-65fcd1ca1a63',
slotId: 'product-page-details-6',
}],
installation: { autoAdd: true },
tagName: 'my-site-plugin',
element: './extensions/site/plugins/my-site-plugin/my-site-plugin.tsx',
settings: './extensions/site/plugins/my-site-plugin/my-site-plugin.panel.tsx',
});CRITICAL: UUID Generation
The must be a unique, static UUID v4 string. Generate a fresh UUID for each extension - do NOT use or copy UUIDs from examples. Replace with a freshly generated UUID like .
idrandomUUID(){{GENERATE_UUID}}"95a28afd-7df1-4e09-9ec1-ce710b0389a0"| Property | Type | Description |
|---|---|---|
| string | Unique static UUID v4 (generate fresh) |
| string | Internal name for the plugin |
| string | Display name in plugin explorer and app dashboard |
| string | Description shown in plugin explorer and app dashboard |
| string | Path to logo file ( |
| array | Array of slot placements where plugin can be added |
| string | ID of the Wix app containing the slot |
| string | ID of the page containing the slot |
| string | ID of the specific slot |
| boolean | Whether to auto-add plugin to slots on app installation |
| string | HTML custom element tag (kebab-case, must contain a hyphen) |
| string | Relative path to plugin component |
| string | Relative path to settings panel component |
每个站点插件在其文件夹中需要一个扩展文件:
typescript
// my-site-plugin.extension.ts
import { extensions } from '@wix/astro/builders';
export default extensions.sitePlugin({
id: '{{GENERATE_UUID}}',
name: 'My Site Plugin',
marketData: {
name: 'My Site Plugin',
description: 'Marketing Description',
logoUrl: '{{BASE_URL}}/my-site-plugin-logo.svg',
},
placements: [{
appDefinitionId: 'a0c68605-c2e7-4c8d-9ea1-767f9770e087',
widgetId: '6a25b678-53ec-4b37-a190-65fcd1ca1a63',
slotId: 'product-page-details-6',
}],
installation: { autoAdd: true },
tagName: 'my-site-plugin',
element: './extensions/site/plugins/my-site-plugin/my-site-plugin.tsx',
settings: './extensions/site/plugins/my-site-plugin/my-site-plugin.panel.tsx',
});重要提示:UUID生成
idrandomUUID(){{GENERATE_UUID}}"95a28afd-7df1-4e09-9ec1-ce710b0389a0"| 属性 | 类型 | 描述 |
|---|---|---|
| string | 唯一的静态UUID v4(需新生成) |
| string | 插件的内部名称 |
| string | 在插件资源管理器和应用仪表板中显示的名称 |
| string | 在插件资源管理器和应用仪表板中显示的描述 |
| string | 图标文件路径( |
| array | 插件可添加到的插槽位置数组 |
| string | 包含插槽的Wix应用ID |
| string | 包含插槽的页面ID |
| string | 具体插槽的标识符 |
| boolean | 应用安装时是否自动将插件添加到插槽中 |
| string | HTML自定义元素标签(短横线命名法,必须包含连字符) |
| string | 插件组件的相对路径 |
| string | 设置面板组件的相对路径 |
Step 2: Register in Main Extensions File
步骤2:在主扩展文件中注册
CRITICAL: After creating the plugin-specific extension file, you MUST read wix-cli-extension-registration and follow the "App Registration" section to update .
src/extensions.tsWithout completing Step 2, the site plugin will not be available in the plugin explorer.
**重要提示:**创建插件专属扩展文件后,必须阅读wix-cli-extension-registration并按照「应用注册」部分的说明更新。
src/extensions.ts未完成步骤2的情况下,站点插件将不会在插件资源管理器中显示。
Examples
示例
For complete examples with all three required files (plugin component, settings panel, extension configuration), see EXAMPLES.md.
Example use cases:
- Best Seller Badge - Customizable badge on product pages with text and color settings
- Booking Confirmation - Custom confirmation message for booking pages
- Product Reviews Summary - Star rating and review count display
- Data-Driven Plugin - Plugin with Wix Data API integration and editor environment handling
如需包含所有三个必填文件(插件组件、设置面板、扩展配置)的完整示例,请查看EXAMPLES.md。
示例用例:
- 畅销商品徽章 - 产品页面上的可自定义徽章,支持文本和颜色设置
- 预订确认信息 - 预订页面的自定义确认消息
- 产品评论摘要 - 星级评分和评论数量展示
- 数据驱动插件 - 集成Wix Data API并处理编辑器环境的插件
Best Practices
最佳实践
Implementation Guidelines
实现指南
- Use inline styles - CSS imports are not supported in custom elements
- Handle editor environment - Show placeholders when in editor mode for data-dependent plugins
- Editor sandboxing - Plugins are sandboxed in the Editor; ,
localStorage, and cookies are restricted. UsesessionStorageto detect editor and mock storage if neededviewMode() - Validate all input - Check required props are present
- Follow naming conventions - kebab-case for all attributes and widget API
- Keep plugins focused - Each plugin should do one thing well
- Test in multiple slots - If supporting multiple placements, test each one
- 使用内联样式 - 自定义元素不支持CSS导入
- 处理编辑器环境 - 对于依赖数据的插件,在编辑器模式下显示占位符
- 编辑器沙箱限制 - 插件在编辑器中处于沙箱环境;、
localStorage和Cookie受到限制。可使用sessionStorage检测编辑器环境并模拟存储viewMode() - 验证所有输入 - 检查必填属性是否存在
- 遵循命名规范 - 所有属性和widget API使用短横线命名法
- 保持插件聚焦 - 每个插件应专注于完成单一功能
- 在多插槽中测试 - 如果支持多个位置,请在每个位置进行测试
Performance Considerations
性能考量
- Keep bundle size small - plugins load on user-facing pages
- Avoid heavy computations on initial render
- Lazy load data when possible
- Use efficient re-rendering patterns
- 保持包体积小巧 - 插件会在用户页面加载
- 避免初始渲染时的大量计算
- 尽可能懒加载数据
- 使用高效的重新渲染模式
Verification
验证
After implementation, use wix-cli-app-validation to validate TypeScript compilation, build, preview, and runtime behavior.
实现完成后,使用wix-cli-app-validation验证TypeScript编译、构建、预览和运行时行为。
Code Quality Requirements
代码质量要求
- Strict TypeScript (no , explicit return types)
any - Native HTMLElement class for plugin components
- React functional components with hooks for settings panels
- Proper error handling and loading states
- No comments
@ts-ignore - Inline styles via template strings (no CSS imports)
- Handle Wix Editor environment when using Wix Data API
- Consistent attribute naming using kebab-case throughout
- 严格TypeScript规范(禁止类型,显式声明返回类型)
any - 插件组件使用原生HTMLElement类
- 设置面板使用React函数式组件和Hooks
- 完善的错误处理和加载状态
- 禁止注释
@ts-ignore - 通过模板字符串使用内联样式(禁止CSS导入)
- 使用Wix Data API时处理Wix编辑器环境
- 全程统一使用短横线命名法命名属性