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

# Install Sleekplan with Vue

> Add the Sleekplan feedback widget to a Vue app, either by pasting the snippet into index.html or by injecting it from your root component's mounted hook.

The Sleekplan widget is a standard script snippet, so adding it to a Vue app takes one of two approaches. Pasting it into `index.html` is the simplest and works for both Vue 2 and Vue 3. Injecting it from a component gives you more control if you need to load it conditionally.

<Info>
  First grab your snippet from [**Settings → Widget**](https://app.sleekplan.com/settings/widget) and copy your `SLEEK_PRODUCT_ID`. See [Install the Sleekplan widget](/help/getting-started/install-widget) for the basics.
</Info>

## Option 1: Add to index.html (recommended)

In a Vue project created with Vite or Vue CLI, open the `index.html` file in your project's `public` folder (or the project root for Vite). Paste the snippet just before the closing `</head>` tag:

```html theme={"system"}
<head>
  <!-- your existing head content -->

  <!-- Sleekplan widget -->
  <script type="text/javascript">window.$sleek=[];window.SLEEK_PRODUCT_ID=YOUR_PRODUCT_ID;(function(){d=document;s=d.createElement("script");s.src="https://client.sleekplan.com/sdk/e.js";s.async=1;d.getElementsByTagName("head")[0].appendChild(s);})();</script>
</head>
```

Replace `YOUR_PRODUCT_ID` with the numeric ID from your snippet. Because it loads asynchronously, it will not block your app from rendering.

## Option 2: Inject from your root component

If you would rather keep the snippet out of `index.html`, or you need to load the widget only for certain users, inject it from the `mounted` hook of your root component (`App.vue`). This runs once, after the app is on the page.

```js theme={"system"}
export default {
  name: "App",
  mounted() {
    window.$sleek = [];
    window.SLEEK_PRODUCT_ID = YOUR_PRODUCT_ID;

    const s = document.createElement("script");
    s.src = "https://client.sleekplan.com/sdk/e.js";
    s.async = true;
    document.getElementsByTagName("head")[0].appendChild(s);
  },
};
```

The same code works with the Composition API inside `onMounted()`:

```js theme={"system"}
import { onMounted } from "vue";

onMounted(() => {
  window.$sleek = [];
  window.SLEEK_PRODUCT_ID = YOUR_PRODUCT_ID;

  const s = document.createElement("script");
  s.src = "https://client.sleekplan.com/sdk/e.js";
  s.async = true;
  document.getElementsByTagName("head")[0].appendChild(s);
});
```

## Nuxt

For a Nuxt app, add the script through `nuxt.config` so it loads on every page:

```js theme={"system"}
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        { children: "window.$sleek=[];window.SLEEK_PRODUCT_ID=YOUR_PRODUCT_ID;" },
        { src: "https://client.sleekplan.com/sdk/e.js", async: true },
      ],
    },
  },
});
```

## Identify your users

After the widget loads, attach your signed-in user with the SDK:

```js theme={"system"}
$sleek.setUser({
  mail: user.email,
  id: user.id,
  name: user.name,
});
```

For confirmed accounts or private boards, use [Single Sign-On](https://sleekplan.com/docs/authentication/single-sign-on) instead. The full API is in the [Developer Docs](https://sleekplan.com/docs/sdk/user-setup).

## Next steps

<CardGroup cols={2}>
  <Card title="Back to install overview" icon="arrow-left" href="/help/getting-started/install-widget">
    The snippet, user identification, and other platforms.
  </Card>

  <Card title="Content Security Policy" icon="shield-halved" href="/help/getting-started/install-widget/content-security-policy">
    Allowlist the Sleekplan domains if your app enforces a CSP.
  </Card>
</CardGroup>
