# How to set up and edit an app integration

## How to set up an app integration

To set up a new custom app, click the "Create app"-button located at the top right of the "[Installed apps](https://docs.struct.com/reference/settings/integration/apps)"-page. If no apps are installed, this button will also appear at the center of the page.

<figure><img src="https://2141378775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuUonpFWM7AJ0xVVXV1tr%2Fuploads%2FfPYKhInbSBSuwlZGfr4E%2Fimage.png?alt=media&#x26;token=9ff3288b-7d76-43aa-b710-f77a66cd6961" alt=""><figcaption><p>Installed apps page</p></figcaption></figure>

This will present you with the "Create app"-page.

<figure><img src="https://2141378775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuUonpFWM7AJ0xVVXV1tr%2Fuploads%2FvmsMD171mt2U8ABMVZqo%2Fimage.png?alt=media&#x26;token=9bc4bafa-277f-4581-b604-fda235e20602" alt=""><figcaption><p>App creation - General settings page</p></figcaption></figure>

During app creation, you must enter a name for the app. You can optionally provide a description to help identify the app’s functionality. The messaging version is automatically set to the latest version of the API used for communication. You can also choose whether the app should be active. Above you can see an example of the setup.

Once done you can proceed by clicking the "Next"-button in the bottom right corner.

<figure><img src="https://2141378775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuUonpFWM7AJ0xVVXV1tr%2Fuploads%2F75mboBOHpeh1dG2SpgUU%2Fimage.png?alt=media&#x26;token=41cea2b1-a06f-4d00-991a-062cc7fb77b7" alt=""><figcaption><p>Extension points setup page</p></figcaption></figure>

You will now be taken to the "Extension points setup"-page.

Here you can add a new extension point by clicking the "Add extension point"-button in the center of the screen.

<figure><img src="https://2141378775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuUonpFWM7AJ0xVVXV1tr%2Fuploads%2FZJCbFpVspOgNsRSuSbP5%2Fimage.png?alt=media&#x26;token=c30c8906-1e13-4d04-824b-b7f75fb0a3e3" alt=""><figcaption><p>Added extension point</p></figcaption></figure>

When creating an extension point, you must provide a label. This label is used both for identification and for key generation to ensure version matching across upgrades. You can also add a description to further clarify its purpose.

You must then select a [type](https://docs.struct.com/reference/settings/integration/apps/apps-details/extension-points/extension-point-types) for the extension point. The selected type determines where in the PIM the extension can be used. For example, it can be a widget displayed on the dashboard or a tab added to a data model in product structures.

<figure><img src="https://2141378775-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FuUonpFWM7AJ0xVVXV1tr%2Fuploads%2FFw8jKlmcgnB0vnG1ZMjb%2Fimage.png?alt=media&#x26;token=a5527097-68a8-40ce-8ade-2111925e8d94" alt=""><figcaption><p>Extension point setup example</p></figcaption></figure>

Above you can see an example of an extension point. After selecting a type, you are required to enter an embed URL, which specifies where the app is hosted. Optionally, you can provide a thumbnail URL, which will be displayed when, in this example, adding the widget to the dashboard.

Once done you can proceed by clicking the "Save"-button.

## How to edit an app integration

To edit a custom app in click the three dots icon at the top right of the app you want to edit. From here click the "Details"-button.

In order to delete an app from the PIM click the "Delete"-button instead.

## Example of custom app

In order to add custom app to the PIM some steps need to be taken. In this guide, we will expand on the steps outlined in the [quickstart](https://docs.struct.com/developer/app-integration/quickstart) guide.

### Setting up the app

To integrate an app into the Struct PIM, start by setting up a TypeScript project. In this example we are using Vite.

We start with creating and navigating to the project folder:

```bash
mkdir my-pim-integration
cd my-pim-integration
```

We then initialize the project with Vite:

```bash
npm create vite@latest .
```

During initilization there are various framworks and variants to choose from. In this example we select the following options:

* `vanilla` for the framework.
* Set the variant to `typeScript`.

In this example the name given to the project is `my-pim-integration`.&#x20;

This setup will create a framework-agnostic TypeScript project ready for further development.

From here we can open the project in VS Code by typing the following in the terminal.

```bash
code .
```

Now in the project you need the following [SDK package](https://www.npmjs.com/package/@structdk/extension-sdk) in order to connect with the PIM. There are also two other packages, one for [UI](https://www.npmjs.com/package/@structdk/ui) and one for [icons](https://www.npmjs.com/package/@structdk/struct-icon) in order to style app in a way that matches the PIM.

Proceed to install the packages through the following command:

```bash
npm install @structdk/ui @structdk/struct-icon @structdk/extension-sdk
```

Once the required packages have been installed, import them at the top of your `src/main.ts` file:

```typescript
import '@structdk/ui/dist/struct-ui.css';
import '@structdk/struct-icon/font/struct-icon-24.css';
import { createStructSDK } from '@structdk/extension-sdk';
import type { TabContextPayload } from '@structdk/extension-sdk';
```

With the dependencies in place, the next step is to create a minimal extension that connects to the PIM, retrieves its context, and listens for changes.

This sets up a minimal app that connects to the PIM, retrieves context, enables auto-resize, and listens for entity and language changes. For more details on each method, refer to the [SDK documentation](https://www.npmjs.com/package/@structdk/extension-sdk).

```typescript
import '@structdk/ui/dist/struct-ui.css';
import '@structdk/struct-icon/font/struct-icon-24.css'
import { createStructSDK } from '@structdk/extension-sdk';
import type { TabContextPayload } from '@structdk/extension-sdk';

async function init() {
  // 1. SDK instance
  const struct = createStructSDK({ hostOrigin: 'https://your-struct-instance.struct.com' });

  // 2. Get context
  const ctx = await struct.actions.getContext<TabContextPayload>();
  console.log('Entity:', ctx.entityType, ctx.entityId);
  console.log('Slug:', ctx.slug);

  // 3. Auto-resize
  struct.actions.enableAutoResize({ maxHeight: 800 });

  // 4. Event listeners
  struct.events.onEntityChangedEvent(payload => console.log('Entity updated:', payload.entityId));
  struct.events.onLanguageChangedEvent(payload => console.log('Language:', payload.currentLanguage));

  // 6. Cleanup
  struct.destroy();
}

// 7. Initialize app on window load
window.addEventListener('load', () => {
  init();
});
```

Enclose the code within an `init()` function to ensure the SDK context is correctly obtained when awaited.

The `window.addEventListener()` ensures the app initializes only once the page is fully loaded. This guarantees accurate embedding and proper refreshing on page reloads.

With this setup in place we can now begin customizing the app. In this case we will be keeping it simple by simply adding a hello world component.

### Adding a component

To begin customizing the app, we’ll create a simple Hello World component. We define it as a function that takes a container element and a click handler. This makes the component self-contained and reusable, allowing it to insert its HTML directly into the container while keeping UI logic separate from the SDK:

```typescript
export function HelloWorld(container: HTMLElement, onClick: () => void) {
  container.innerHTML = `
    <div class="card p-4 space-y-4">
      <h1 class="text-xl font-semibold">Hello World</h1>
      <button class="btn btn-primary">
        <span class="si-24 si-button-play" aria-hidden="true"></span>
        Click me
      </button>
    </div>`;

  const button = container.querySelector<HTMLButtonElement>('.btn');
  button?.addEventListener('click', onClick);
}
```

Once the component is defined, we render it in `src/main.ts`. We create a sub-containers for the components and insert them into the root container `app` defined in the `index.html`.

```typescript
const app = document.getElementById('app');
if (app) {
  
    const helloContainer = document.createElement('div');
    app.appendChild(helloContainer);

  HelloWorld(helloContainer, () => {
    struct.actions.showSnackbarMessage({
      message: 'Hello World clicked!',
      placement: 'top',
      isError: false
    });
  });
}

// 7. Initialize app on window load
window.addEventListener('load', () => {
  init();
});
```

When the button is clicked, the handler runs and triggers an SDK action, showing a snackbar message in the PIM.

Now the app is ready to be integrated into the PIM. Now all you need is to ensure that all dependecies are installed by entering the following command:

```bash
npm install
```

With this you can now run the app through the following command and integrate it with the presented localhost URL into the app by following the guide above.

```bash
npm run dev
```
