> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Vue 3

> Embed StackOne Hub in a Vue 3 app using the <stackone-hub> custom element

Use the `<stackone-hub>` custom element from `@stackone/hub` in any Vue 3 template.

<Steps>
  <Step title="Install the package">
    <CodeGroup>
      ```bash npm theme={null}
      npm install @stackone/hub
      ```

      ```bash yarn theme={null}
      yarn add @stackone/hub
      ```

      ```bash pnpm theme={null}
      pnpm add @stackone/hub
      ```
    </CodeGroup>
  </Step>

  <Step title="Tell Vue that stackone-hub is a custom element">
    Vue's template compiler treats unknown tags as Vue components by default. Mark `stackone-hub` as a custom element so it falls through to the DOM:

    ```ts theme={null}
    // vite.config.ts
    import vue from '@vitejs/plugin-vue';
    import { defineConfig } from 'vite';

    export default defineConfig({
      plugins: [
        vue({
          template: {
            compilerOptions: {
              isCustomElement: (tag) => tag === 'stackone-hub',
            },
          },
        }),
      ],
    });
    ```
  </Step>

  <Step title="Register the element at app entry">
    The import is side-effecting — it registers `<stackone-hub>` on `customElements`.

    ```ts theme={null}
    // src/main.ts
    import '@stackone/hub/webcomponent';
    import { createApp } from 'vue';
    import App from './App.vue';

    createApp(App).mount('#app');
    ```
  </Step>

  <Step title="Get a session token from your backend">
    <Snippet file="guides/web-component-token-step.mdx" />
  </Step>

  <Step title="Add the element and listen for events">
    ```vue theme={null}
    <script setup lang="ts">
    import { onBeforeUnmount, onMounted, ref, useTemplateRef } from 'vue';

    const token = ref('');
    const hubRef = useTemplateRef<HTMLElement>('hub');

    const onSuccess = (event: Event) => {
      const detail = (event as CustomEvent).detail;
      console.log('Connected:', detail.id, detail.provider);
    };
    const onClose = () => console.log('Closed');

    onMounted(async () => {
      token.value = await retrieveConnectSessionToken();
      hubRef.value?.addEventListener('success', onSuccess);
      hubRef.value?.addEventListener('close', onClose);
    });

    onBeforeUnmount(() => {
      hubRef.value?.removeEventListener('success', onSuccess);
      hubRef.value?.removeEventListener('close', onClose);
    });
    </script>

    <template>
      <stackone-hub
        ref="hub"
        :token="token"
        mode="integration-picker"
        height="600px"
      ></stackone-hub>
    </template>
    ```
  </Step>
</Steps>

## Attribute reference

Vue passes `:prop="value"` bindings through as HTML attributes when the tag is registered as a custom element. All scalar `StackOneHub` props map to kebab-case attributes — see the [vanilla guide](/guides/web-component-vanilla#attribute-reference) for the full table.

## Events

Native DOM `CustomEvent`s on the element:

| Event     | `event.detail`                     |
| --------- | ---------------------------------- |
| `success` | `{ id: string; provider: string }` |
| `close`   | `undefined`                        |

Vue's `@event` shorthand does **not** fire on native DOM `CustomEvent`s — Vue's template handlers assume Vue-emitted events. Subscribe with `addEventListener` via a `ref` instead.

## Next steps

<CardGroup cols={2}>
  <Card title="Backend setup" icon="server" href="/platform/connect-your-backend-with-stackone">
    Generate session tokens from your backend.
  </Card>

  <Card title="Filter connectors" icon="filter" href="/guides/embedding-stackone-hub#hub-behavior-customization">
    Restrict the Hub to a single provider or category.
  </Card>
</CardGroup>
