# Integration Guide

## Add floors.js to _Vue & Nuxt_

One script tag in your index.html or nuxt.config. floors.js detects Vue Router navigation automatically — no plugin, no composable, no npm install.

## How it works

floors.js patches the browser's `pushState` and `replaceState` methods and listens to `popstate` events. Vue Router uses the History API under the hood, so room changes happen automatically on every navigation — no extra wiring needed.

When a visitor navigates from `/dashboard` to `/settings`, floors.js detects the URL change and moves them to the "settings" room. Other visitors on the same page see them arrive in real-time.

## Installation

Two setups depending on your framework. Both work the same way.

### Vue 3 (Vite) Recommended

Add the script tag to your `index.html` before the closing `</body>` tag. Vite serves this file as-is, so the script loads on every page.

```
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>My Vue App</title></head><body><div id="app"></div><script type="module" src="/src/main.ts"></script><script src="https://floorsjs.com/embed.js" data-key="flr_..."></script></body></html>
```

### Nuxt 3

Add the script to your `nuxt.config.ts` using the `app.head` option. Nuxt injects it into every page automatically.

```
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          src: 'https://floorsjs.com/embed.js',
          'data-key': 'flr_...'
        }
      ]
    }
  }
})
```

## Works with Vue Router

Both **history mode** and **hash mode** work out of the box. floors.js reads the browser URL to determine the current room name.

- **History mode** — `/pricing` becomes the "pricing" room. floors.js detects changes via the patched History API.
- **Hash mode** — `/#/pricing` becomes the "pricing" room. floors.js listens to `hashchange` events automatically.
- **Nested routes** — `/dashboard/analytics` becomes the "dashboard/analytics" room. The full path is used.

No router guards, no navigation hooks, no `watch` on `$route`. It just works.

## Configuration

floors.js reads optional attributes from the script tag:

- **data-key** (required) — your site key, e.g. `flr_abc123`
- **data-server** — custom WebSocket server URL, for self-hosted deployments
- **data-name** — set a default display name for the current visitor

Example with all options

```
<script src="https://floorsjs.com/embed.js" data-key="flr_abc123" data-server="wss://your-server.com" data-name="Team Member"></script>
```

## FAQ

### Do I need a Vue plugin?

No. floors.js is completely framework-agnostic. It runs as a standalone script that hooks into browser APIs, not Vue internals. No plugin, no composable, no `app.use()` call needed.

### Does it work with Nuxt SSR?

Yes. The script loads and executes client-side only. It doesn't run during server-side rendering, so there are no hydration mismatches or SSR errors. The widget mounts after the page is interactive in the browser.

### Does it interfere with Pinia or Vuex?

No. floors.js manages its own state entirely through a WebSocket connection and localStorage. It doesn't read from or write to any Vue store. No store module, no actions, no shared state to worry about.

### Does it affect bundle size?

No. floors.js is an external script loaded from a CDN, not an npm package. It never enters your Vite build pipeline. Three.js (the 3D renderer) is loaded asynchronously from a separate CDN. Your Vue or Nuxt bundle stays exactly the same size.

### What about Vue devtools?

floors.js doesn't register as a Vue component or plugin, so it won't appear in Vue devtools. It lives outside the Vue component tree entirely. This also means it can't accidentally break your component hierarchy or reactivity system.
