Add a custom element extension to your new Wix CLI project as part of migrating an app from the legacy Wix CLI.
| Legacy path | New path |
|---|---|
src/site/widgets/custom-elements/<name>/element.json | src/extensions/site/widgets/<name>/<name>.extension.ts |
src/site/widgets/custom-elements/<name>/element.tsx | src/extensions/site/widgets/<name>/<name>.tsx |
src/site/widgets/custom-elements/<name>/panel.tsx | src/extensions/site/widgets/<name>/<name>.panel.tsx |
src/site/widgets/custom-elements/<name>/element.module.css | src/extensions/site/widgets/<name>/<name>.module.css |
Note: <name> is your extension's folder name in the legacy project. The new folder and files use the same name.
In the new project:
src/extensions/site/widgets/<name>/.src/site/widgets/custom-elements/<name>/ folder, copy the following files into the new folder, and rename them:
element.tsx to <name>.tsxpanel.tsx, if present, to <name>.panel.tsxelement.module.css, if present, to <name>.module.cssDon't copy the legacy element.json file. You recreate its values in <name>.extension.ts.
In <name>.tsx and <name>.panel.tsx:
In the new project:
In src/extensions/site/widgets/<name>/, create <name>.extension.ts.
Add the following code, and set each field to the value the table below specifies:
| Field | Source in legacy project | What to specify |
|---|---|---|
id | id in element.json | Copy source as is |
name | name in element.json | Copy source as is |
width | width in element.json | Copy source as is, including allowStretch and stretchByDefault if your legacy config sets them. Only defaultWidth is required. |
height | height in element.json | Copy source as is |
installation.autoAdd | installation.autoAddToSite in element.json | Copy source as is, or false if the legacy config doesn't set it |
tagName | None | The extension folder name |
element | None | Path to <name>.tsx, relative to src/ |
Add any of the following fields that apply, inside the same object. Add essential to the existing installation object, not as a second installation field:
| Field | Source in legacy project | What to specify | Condition |
|---|---|---|---|
installation.essential | installation.essential in element.json | Copy source as is | Only if your legacy element.json sets it |
presets | presets in element.json | Copy the preset's id and thumbnailUrl, and add a name, which legacy presets don't have. Use the element's name, which is the preset name the legacy CLI writes to the app manifest. If the thumbnailUrl references a local assets/ folder, see Update the preset thumbnail URL. | Only if your legacy element.json sets it |
behaviors | behaviors in element.json, such as the dashboard page the widget links to | Copy source as is | Only if your legacy element.json sets it |
settings | None | Path to <name>.panel.tsx, relative to src/ | Only if the legacy extension has a panel.tsx file |
Important:
The id must match the value from the legacy element.json. Otherwise, the new entry is treated as a separate extension instead of a continuation of the legacy one.
A legacy custom element has at most 1 preset. If its thumbnailUrl references a local assets/ folder, replace the value with {{BASE_URL}}/thumbnail.png:
Move the image itself into the new project's public/ folder, which is where {{BASE_URL}} resolves to.
In the new project, in src/extensions.ts:
Import the extension:
Add a .use() call for it to the app() chain, on its own line:
Return to Install the extension's dependencies in the main migration guide.
Last updated: 10 November 2026