> Portal Navigation:
> 
> - Append `.md` to any URL under `https://dev.wix.com/docs/` to get its markdown version.
> - Pages are either content pages (article or reference text) or menu pages (a list of links to child pages).
> - To get a menu page, truncate any URL to a parent path and append `.md` (e.g. `https://dev.wix.com/docs/sdk.md`, `https://dev.wix.com/docs/sdk/core-modules.md`).
> - Top-level index of all portals: https://dev.wix.com/docs/llms.txt
> - Full concatenated docs: https://dev.wix.com/docs/llms-full.txt

## Resource: Site Plugin Extension Files and Code

## Article: Site Plugin Extension Files and Code

## Article Link: https://dev.wix.com/docs/site-extensions/site-plugins/site-plugin-extension-files-and-code.md

## Article Content:

# Site Plugin Extension Files and Code

When you add a [site plugin](https://dev.wix.com/docs/overview/extensions-framework/site-extensions/site-plugins.md) extension, the generated files land under `src/extensions/site/plugins/<plugin-folder>/`, a logo file lands in the project's `public/` folder, and the extension is registered in your project's `extensions.ts`.

This file set is the same whether you add the plugin in a Studio Two site project or in a Wix CLI app.

```text
public/
└── <plugin-folder>-logo.svg
src/
└── extensions/
    └── site/
        └── plugins/
            └── <plugin-folder>/
                ├── <plugin-folder>.extension.ts
                ├── <plugin-folder>.tsx
                └── <plugin-folder>.panel.tsx
```

| File | What it's for |
|------|---------------|
| `<plugin-folder>.extension.ts` | The [configuration file](#configuration-file) for the plugin ID, name, slots, tag name, and file paths. |
| `<plugin-folder>.tsx` | The [custom element](#custom-element) that renders in the slot. |
| `<plugin-folder>.panel.tsx` | The [settings panel](#settings-panel), a React component where a Wix user customizes the plugin in the editor. |
| `<plugin-folder>-logo.svg` | The plugin's logo, referenced by `marketData.logoUrl` in the configuration file. |

## Configuration file

The `<plugin-folder>.extension.ts` file declares the plugin with `extensions.sitePlugin()`.

Import `extensions` from the package your project uses:

```ts
// Studio Two site
import { extensions } from '@wix/custom-extensions';
```

```ts
// Wix CLI app
import { extensions } from '@wix/astro/builders';
```

The following example declares a plugin named Checkout Banner for the Checkout page's `checkout:top` slot:

```ts
export default extensions.sitePlugin({
  id: '5a128aea-7d45-465b-a18b-382a9939582f',
  name: 'Checkout Banner',
  marketData: {
    name: 'Checkout Banner',
    description: 'Marketing Description',
    logoUrl: '{{BASE_URL}}/checkout-banner-logo.svg',
  },
  placements: [{
    appDefinitionId: '1380b703-ce81-ff05-f115-39571d94dfcd',
    widgetId: '14fd5970-8072-c276-1246-058b79e70c1a',
    slotId: 'checkout:top',
  }],
  installation: { autoAdd: true },
  tagName: 'checkout-banner',
  element: './extensions/site/plugins/checkout-banner/checkout-banner.tsx',
  settings: './extensions/site/plugins/checkout-banner/checkout-banner.panel.tsx',
});
```

Keep this file. If you add a site plugin yourself, include it. Don't delete it after the plugin is generated.

### Configuration fields

| Field | Type | Description |
|--|--|--|
| `id` | string | Plugin ID as a GUID. It must be unique across all extensions in the project. |
| `name` | string | The plugin's name. |
| `marketData` | object | Optional. How the plugin is presented to Wix users. |
| `marketData.name` | string | The plugin name that Wix users see. |
| `marketData.description` | string | The plugin description that Wix users see. |
| `marketData.logoUrl` | string | URL of the plugin's logo. The generated value points to the logo file in the project's `public/` folder. If you rename that file, update this value. If you delete it, remove this field. |
| `placements` | array | The slots the plugin can fill. The generated file lists the slot you chose. Add an object for each other slot the plugin can fill. For each widget's `appDefinitionId`, `widgetId`, and `slotId` values, see the **Legacy `placements` values** section of the widget's page in [About Slots](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/site-plugins/supported-wix-app-pages/about-slots.md). `extensions.sitePlugin()` doesn't accept the `placementsSlotIds` array that those pages recommend. |
| `placements.appDefinitionId` | string | ID of the Wix app that owns the widget, such as Wix eCommerce. |
| `placements.widgetId` | string | ID of the widget that contains the slot, such as the Checkout page. |
| `placements.slotId` | string | ID of the slot in that widget, such as `checkout:top`. |
| `installation.autoAdd` | boolean | For a plugin in an app, whether Wix adds the plugin to the first available slot in `placements` when a Wix user installs the app. Automatic placement might not work in some slots, such as the Checkout and Side Cart slots. Their pages in [About Slots](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/site-plugins/supported-wix-app-pages/about-slots.md) say so. |
| `tagName` | string | The custom element's tag name. It must follow the [custom element naming rules](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#name): lowercase, with at least one hyphen. A generated plugin uses the plugin folder name. |
| `element` | string | Path to the custom element file, relative to the project's `src/` directory. |
| `settings` | string | Path to the settings panel file, relative to the project's `src/` directory. |

## Custom element

The `<plugin-folder>.tsx` file defines the plugin as a [custom element](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements): a class that extends `HTMLElement`. The class must be the file's default export. Wix registers it under the configuration's `tagName`.

A generated plugin renders a title from its `display-name` attribute, and renders again when the attribute changes:

```ts
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 Widget's Title`;

    this.innerHTML = `
      <div style="font-size: 16px; padding: 16px; border: 1px solid #ccc; border-radius: 8px; margin: 16px; height: 50%;">
        <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;
```

You can write code in other files and import it into this file.

### Slot data

A slot can pass data to the plugin through its plugin API, such as the ID of the product in view. Wix sets each plugin API property and function on the element as a JavaScript property with the same name. Wix also sets each plugin API property as an attribute:

- The attribute name is the property name in kebab case. For example, `productId` becomes `product-id`.
- A value that isn't a primitive arrives as a JSON string. Use `JSON.parse()` to read it.

To read an attribute, list it in `observedAttributes` and handle it in `attributeChangedCallback()`, the same way the generated element reads `display-name`. To receive a function, use a setter. For the setter pattern, see [Connect to the plugin's API](https://dev.wix.com/docs/build-apps/develop-your-app/develop-a-self-managed-app/supported-extensions/site-extensions/site-widgets-and-plugins/add-site-plugin-extensions-with-custom-elements.md#connect-to-the-plugins-api).

For the plugin API of each slot, see [About Slots](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/site-plugins/supported-wix-app-pages/about-slots.md).

> **Note:** The screenshots and slot locations in About Slots and its widget pages might not match every Wix editor. In some editors, a widget and its slots might look different, or not exist.

## Settings panel

The `<plugin-folder>.panel.tsx` file exports a React component, the plugin's settings panel. A Wix user opens it in the editor to customize the plugin.

The panel reads and sets the plugin's properties with the [Widget API](https://dev.wix.com/docs/sdk/host-modules/editor/widget/introduction.md) from `@wix/editor`. Each property is bound to an attribute of the custom element, so a change in the panel updates the element. A generated panel has a single **Display Name** field for the `display-name` property:

```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;
```

Inside the panel you can use the [Wix Design System](https://dev.wix.com/docs/build-apps/develop-your-app/design/about-the-wix-design-system.md) for the panel's UI and the [Wix JavaScript SDK](https://dev.wix.com/docs/sdk.md) to access Wix data.

## See also

- [About Site Plugins](https://dev.wix.com/docs/site-extensions/site-plugins/about-site-plugins.md)
- [Site Plugins](https://dev.wix.com/docs/overview/extensions-framework/site-extensions/site-plugins.md)
- [About Slots](https://dev.wix.com/docs/build-apps/develop-your-app/extensions/site-extensions/site-plugins/supported-wix-app-pages/about-slots.md)
- [Widget API](https://dev.wix.com/docs/sdk/host-modules/editor/widget/introduction.md)