Wix Site Plugin Builder
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, Wix eCommerce), extending their functionality and user experience.
Site owners can place site plugins into UI slots using the plugin explorer in Wix editors.
Quick Start Checklist
Follow these steps in order when creating a site plugin:
Create plugin folder:
src/extensions/site/plugins/
${ displayName }
This is a Site Plugin generated by Wix CLI.
Edit your element's code to change this text.
- `
- ;
- }
- }
- export
- default
- MyElement
- ;
- Key Points:
- Extend
- HTMLElement
- class directly
- Define
- observedAttributes
- static getter to list reactive attributes
- Attributes use
- kebab-case
- (e.g.,
- display-name
- ,
- bg-color
- )
- Implement
- connectedCallback()
- for initial render
- Implement
- attributeChangedCallback()
- to re-render when attributes change
- Use inline styles via template strings
- Use
- this.getAttribute('attribute-name')
- to read attribute values
- Wix handles
- define()
- for you — do NOT call
- customElements.define()
- in your code
- Settings Panel Pattern
- // 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
- widget.getProp()
- and
- widget.setProp()
- use
- kebab-case
- (e.g.,
- "display-name"
- )
- Always update both local state AND widget prop in onChange handlers
- Widget properties are bound to custom element attributes — changes automatically update the corresponding attribute
- Wrap content in
- WixDesignSystemProvider > SidePanel > SidePanel.Content
- Use WDS components from
- @wix/design-system
- Import
- @wix/design-system/styles.global.css
- for styles
- Include
- aria-label
- for accessibility
- Color & Font Picker Fields
- Site plugin settings panels can use
- inputs.selectColor()
- and
- inputs.selectFont()
- from
- @wix/editor
- to open the native Wix Editor color and font picker dialogs.
- ColorPickerField
- Opens the Wix color picker with theme colors, gradients, and more —
- NOT
- a basic HTML
- .
- import
- React
- ,
- {
- type
- FC
- }
- from
- 'react'
- ;
- import
- {
- inputs
- }
- from
- '@wix/editor'
- ;
- import
- {
- FormField
- ,
- Box
- ,
- FillPreview
- ,
- SidePanel
- }
- from
- '@wix/design-system'
- ;
- interface
- ColorPickerFieldProps
- {
- label
- :
- string
- ;
- value
- :
- string
- ;
- onChange
- :
- (
- value
- :
- string
- )
- =>
- void
- ;
- }
- export
- const
- ColorPickerField
- :
- FC
- <
- ColorPickerFieldProps
- >
- =
- (
- {
- label
- ,
- value
- ,
- onChange
- ,
- }
- )
- =>
- (
- <
- SidePanel
- .
- Field
- >
- <
- FormField label
- =
- {
- label
- }
- >
- <
- Box width
- =
- "30px"
- height
- =
- "30px"
- >
- <
- FillPreview
- fill
- =
- {
- value
- }
- onClick
- =
- {
- (
- )
- =>
- inputs
- .
- selectColor
- (
- value
- ,
- {
- onChange
- :
- (
- val
- )
- =>
- {
- if
- (
- val
- )
- onChange
- (
- val
- )
- ;
- }
- }
- )
- }
- /
- >
- <
- /
- Box
- >
- <
- /
- FormField
- >
- <
- /
- SidePanel
- .
- Field
- >
- )
- ;
- FontPickerField
- Opens the Wix font picker with font family, size, bold, italic, and other typography features.
- import
- React
- ,
- {
- type
- FC
- }
- from
- 'react'
- ;
- import
- {
- inputs
- }
- from
- '@wix/editor'
- ;
- import
- {
- FormField
- ,
- Button
- ,
- Text
- ,
- SidePanel
- }
- from
- '@wix/design-system'
- ;
- interface
- FontValue
- {
- font
- :
- string
- ;
- textDecoration
- :
- string
- ;
- }
- interface
- FontPickerFieldProps
- {
- label
- :
- string
- ;
- value
- :
- FontValue
- ;
- onChange
- :
- (
- value
- :
- FontValue
- )
- =>
- void
- ;
- }
- export
- const
- FontPickerField
- :
- FC
- <
- FontPickerFieldProps
- >
- =
- (
- {
- label
- ,
- value
- ,
- onChange
- ,
- }
- )
- =>
- (
- <
- SidePanel
- .
- Field
- >
- <
- FormField label
- =
- {
- label
- }
- >
- <
- Button
- size
- =
- "small"
- priority
- =
- "secondary"
- onClick
- =
- {
- (
- )
- =>
- inputs
- .
- selectFont
- (
- value
- ,
- {
- onChange
- :
- (
- val
- )
- =>
- onChange
- (
- {
- font
- :
- val
- .
- font
- ,
- textDecoration
- :
- val
- .
- textDecoration
- ||
- ""
- }
- )
- }
- )
- }
- fullWidth
- >
- <
- Text size
- =
- "small"
- ellipsis
- >
- Change Font
- <
- /
- Text
- >
- <
- /
- Button
- >
- <
- /
- FormField
- >
- <
- /
- SidePanel
- .
- Field
- >
- )
- ;
- Important:
- Always use
- inputs.selectColor()
- from
- @wix/editor
- with
- FillPreview
- — do NOT use
- Always use
- inputs.selectFont()
- from
- @wix/editor
- with the callback pattern
- inputs.selectFont(value, { onChange })
- Import
- inputs
- from
- @wix/editor
- (not from
- @wix/sdk
- )
- Attribute Naming Convention
- Site plugins use
- kebab-case
- consistently for HTML attributes:
- File
- Convention
- Example
.tsx - (getAttribute)
- kebab-case
- this.getAttribute('display-name')
.tsx - (observedAttributes)
- kebab-case
- ['display-name', 'bg-color']
.panel.tsx - (widget API)
- kebab-case
- widget.getProp('display-name')
- Output Structure
- Site plugins live under
- src/extensions/site/plugins
- . Each plugin has its own folder with files named after the plugin.
- src/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)
- References
- Topic
- Reference
- Complete Examples
- EXAMPLES.md
- Slots (App IDs, multiple placements, finding slots)
- SLOTS.md
- WDS Components
- wds-docs
- 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), checkout and side cart (Wix eCommerce), booking pages (Wix Bookings), service pages, event pages, and blog post pages. For supported pages, common Wix App IDs, and how to find slot IDs, see SLOTS.md . Extension Registration Extension registration is MANDATORY and has TWO required steps. Step 1: Create Plugin-Specific Extension File Each site plugin requires an extension file in its folder: // 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 id must be a unique, static UUID v4 string. Generate a fresh UUID for each extension - do NOT use randomUUID() or copy UUIDs from examples. Replace {{GENERATE_UUID}} with a freshly generated UUID like "95a28afd-7df1-4e09-9ec1-ce710b0389a0" . Property Type Description id string Unique static UUID v4 (generate fresh) name string Internal name for the plugin marketData.name string Display name in plugin explorer and app dashboard marketData.description string Description shown in plugin explorer and app dashboard marketData.logoUrl string Path to logo file ( {{BASE_URL}} resolves to public folder) placements array Array of slot placements where plugin can be added placements.appDefinitionId string ID of the Wix app containing the slot placements.widgetId string ID of the page containing the slot placements.slotId string ID of the specific slot installation.autoAdd boolean Whether to auto-add plugin to slots on app installation tagName string HTML custom element tag (kebab-case, must contain a hyphen) element string Relative path to plugin component settings string Relative path to settings panel component Step 2: Register in Main Extensions File 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.ts . Without completing Step 2, the site plugin will not be available in the plugin explorer. Checkout Plugins If you are building a plugin for the checkout page , it may not support automatic addition upon installation. You must create a dashboard page to provide users with a way to add the plugin to their site. See EXAMPLES.md for the dashboard page pattern. 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 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 Do not call define() - Wix handles customElements.define() for you automatically 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 Support both Stores versions - Include placements for both old and new Wix Stores product pages for maximum compatibility Editor Sandboxing Site plugins are sandboxed when rendered in the editor. This means they're treated as if they come from a different domain, which impacts access to browser storage APIs. Restricted APIs in the editor: localStorage and sessionStorage (Web Storage API) document.cookie (Cookie Store API) IndexedDB API Cache API How to handle sandboxing: Use the viewMode() function from @wix/site-window to check the current mode before accessing restricted APIs: import { window as wixWindow } from '@wix/site-window' ; const viewMode = await wixWindow . viewMode ( ) ; if ( viewMode === 'Site' ) { const item = localStorage . getItem ( 'myKey' ) ; } else { // Mock storage or modify API usage for editor mode } Using Wix SDK Modules in Site Plugins Site plugins can import and use Wix SDK modules directly — you do NOT need createClient() . The Wix runtime provides the client context automatically. // ✅ CORRECT — Import SDK modules directly import { items } from "@wix/data" ; import { currentCart } from "@wix/ecom" ; import { products } from "@wix/stores" ; class MyPlugin extends HTMLElement { async loadData ( ) { // Call SDK methods directly — no createClient needed const result = await items . query ( "MyCollection" ) . find ( ) ; const cart = await currentCart . getCurrentCart ( ) ; const productList = await products . queryProducts ( ) . limit ( 10 ) . find ( ) ; } } // ❌ WRONG — Do NOT use createClient in site plugins import { createClient } from "@wix/sdk" ; const wixClient = createClient ( { modules : { items , products } } ) ; await wixClient . items . query ( ... ) ; // Wrong — API surface differs through client 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