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

# React, Next.js, Vue and others

> Add the Paperlink AI widget to React, Next.js, Vue and plain HTML sites.

Every framework uses the same script tag. Pick the tab for your framework. For a floating widget on every page, add the tag with `data-api-key` to your root layout.

**Next.js (App Router)**

Use `next/script` with the data attributes. Add the component to your root layout. The widget then shows on every page.

```tsx app/layout.tsx theme={"dark"}
import Script from 'next/script';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://api.paperlinkai.com/widget.js"
          data-api-key="pl_live_..."
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}
```

To start the widget from a component, remove `data-api-key` from the `Script` element. Then use the component from the React tab. Add `'use client'` at the top of the component file, because `init` runs only in the browser.

**React**

Add the script tag without `data-api-key` to `index.html`.

```html index.html theme={"dark"}
<script src="https://api.paperlinkai.com/widget.js" async></script>
```

Start the widget in `useEffect`. Call `destroy()` in the cleanup function.

```tsx PaperlinkWidget.tsx theme={"dark"}
import { useEffect } from 'react';

export function PaperlinkWidget() {
  useEffect(() => {
    let chat: PaperlinkAI.ChatInstance | undefined;
    let unmounted = false;

    window.PaperlinkAIChatQueue = window.PaperlinkAIChatQueue || [];
    window.PaperlinkAIChatQueue.push((PaperlinkAIChat) => {
      if (!unmounted) chat = PaperlinkAIChat.init({ apiKey: 'pl_live_...' });
    });

    return () => {
      unmounted = true;
      chat?.destroy();
    };
  }, []);

  return null;
}
```

Render `<PaperlinkWidget />` once, near the root of your app. The `unmounted` flag stops a late `init` after the component is gone.

**Vue 3**

Add the script tag without `data-api-key` to `index.html`.

```html index.html theme={"dark"}
<script src="https://api.paperlinkai.com/widget.js" async></script>
```

Start the widget in `onMounted`. Call `destroy()` in `onUnmounted`.

```vue PaperlinkWidget.vue theme={"dark"}
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue';

let chat: PaperlinkAI.ChatInstance | undefined;
let unmounted = false;

onMounted(() => {
  window.PaperlinkAIChatQueue = window.PaperlinkAIChatQueue || [];
  window.PaperlinkAIChatQueue.push((PaperlinkAIChat) => {
    if (!unmounted) chat = PaperlinkAIChat.init({ apiKey: 'pl_live_...' });
  });
});

onUnmounted(() => {
  unmounted = true;
  chat?.destroy();
});
</script>

<template></template>
```

Use `<PaperlinkWidget />` once, in your root component.

**Plain HTML**

Paste the script tag before `</body>`.

```html Paste before </body> theme={"dark"}
<script src="https://api.paperlinkai.com/widget.js" data-api-key="YOUR_API_KEY" async></script>
```

In every sample, replace `pl_live_...` with your API key. Add your site to Allowed origins in the dashboard.

## TypeScript

The React and Vue samples use `window.PaperlinkAIChatQueue` and the `PaperlinkAI` namespace. Add the types file to your project, as [TypeScript types](https://paperlinkai.com/docs/developers/install/script-tag.md#typescript-types) explains. Without it, TypeScript reports that these names do not exist.

## Single-page apps

A floating widget stays on the page when your router changes the route. The widget is attached to `document.body`, so the conversation continues on the next route. Start it once, in the root layout or the root component.

For an inline widget on one route, start it in the component of that route. Call `destroy()` when the component unmounts, as the samples above do. If the visitor returns to the route, the new widget shows the same conversation.

> **[Inline mode](https://paperlinkai.com/docs/developers/configure/inline-mode.md)**
>
> Put the widget inside a container on your page instead of a floating launcher.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.