Migrate a Custom Element Extension

This guide explains how to add a custom element extension to your new Wix CLI project as part of migrating an app from the legacy Wix CLI.

Folder structure

LegacyNew
src/site/widgets/custom-elements/<name>/element.jsonsrc/extensions/site/widgets/<name>/<name>.extension.ts
src/site/widgets/custom-elements/<name>/element.tsxsrc/extensions/site/widgets/<name>/<name>.tsx
src/site/widgets/custom-elements/<name>/panel.tsxsrc/extensions/site/widgets/<name>/<name>.panel.tsx
src/site/widgets/custom-elements/<name>/plugin.module.csssrc/extensions/site/widgets/<name>/<name>.module.css

Note: The custom-elements/ wrapper directory is removed in the new structure. Files move up 1 level to src/extensions/site/widgets/<name>/.

Step 1 | Move and rename files

To move existing files into the new project:

  1. In the new project, create the folder src/extensions/site/widgets/<name>/.
  2. Copy and rename the files:
    • element.tsx<name>.tsx
    • panel.tsx<name>.panel.tsx
    • plugin.module.css<name>.module.css (if present)
  3. Update import references in the .tsx files to use the new filenames.
  4. Fix any other import paths in the .tsx files if needed, including imports of backend code.

Don't copy the old element.json file. It is replaced by a new .extension.ts file.

Step 2 | Create the extension file

In src/extensions/site/widgets/<name>/, create <name>.extension.ts:

Copy
FieldSourceRequired
idid from element.jsonYes. Must match legacy value to preserve the extension.
namename from element.jsonYes
widthwidth from element.json. Use defaults if not set.Yes
heightheight from element.json. Use defaults if not set.Yes
installation.autoAddinstallation.autoAddToSite or installation.autoAdd from element.jsonYes. Use false if not set.
installation.essentialinstallation.essential from element.jsonNo
presetspresets array from element.jsonNo
tagNameUse the extension folder nameYes
elementPath to <name>.tsx, relative to src/Yes
settingsPath to <name>.panel.tsx, relative to src/Yes

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.

Preset thumbnail URLs

If the legacy element.json has presets with thumbnail URLs that reference a local assets/ folder, replace them with {{BASE_URL}}/thumbnail.png:

Copy

Step 3 | Register the extension

In the new project, in src/extensions.ts, import the extension and add it with .use():

Copy

Step 4 | Return to the main migration guide

Return to the Test, build, and release step in the main migration guide.

Last updated: 29 June 2026

Did this help?