# SDK — Vite (/docs/sdk/vite)



{/* AGENT-4-OUTPUT-PENDING: confirm whether `@layers/vite-plugin` ships standalone or whether the standard `@layers/client` install is sufficient. */}

The Layers SDK works in any Vite-built SPA via `@layers/client`. Vite's build is build-time-only — there is no runtime env, so every Layers config that varies per environment must be a `VITE_*` env var baked at build.

## Install [#install]

```bash
npm i @layers/client
```

## Initialize [#initialize]

In your app entrypoint (`src/main.tsx`):

```tsx title="src/main.tsx"
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { LayersClient } from '@layers/client';
import App from './App';

const layers = new LayersClient({
  apiKey: 'unused-but-required-by-type',
  appId: import.meta.env.VITE_LAYERS_APP_ID,
  environment: import.meta.env.MODE === 'production' ? 'production' : 'development',
});
await layers.init();

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App layers={layers} />
  </StrictMode>,
);
```

Pass the client through context or a single shared instance — there is no `<LayersProvider>` package today. The pattern from the [Next.js guide](/docs/sdk/nextjs) (a tiny React context wrapper) translates directly.

## Auto-screen on route changes [#auto-screen-on-route-changes]

If you use TanStack Router, React Router, or any router that exposes a "current path" hook, fire `layers.screen()` on every change:

```tsx
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';

function PageTracker({ layers }) {
  const { pathname } = useLocation();
  useEffect(() => {
    layers.screen(pathname).catch(() => {});
  }, [pathname]);
  return null;
}
```

For React Router specifically, see [the dedicated React Router guide](/docs/sdk/react-router).

## Environment variables [#environment-variables]

| Var                           | Purpose                                                                              | Where it must live                                                                    |
| ----------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| `VITE_LAYERS_APP_ID`          | The SDK app id from [`POST /sdk-apps`](/docs/api/reference/sdk-apps/create-sdk-app). | `.env`, `.env.production`. **Also** in `app/Dockerfile` `ARG`/`ENV` if you Dockerize. |
| `VITE_LAYERS_INGEST_ENDPOINT` | Override the default ingest URL — for [custom domain](/docs/sdk/custom-domain).      | Same as above.                                                                        |

Vite SPAs inline `VITE_*` at build time. After changing the value, you must rebuild — restarting the dev server is not enough on a previously-built bundle.

## Dev-server proxy snippet [#dev-server-proxy-snippet]

If you've configured a [custom domain](/docs/sdk/custom-domain) for production but want to hit `https://in.layers.com` in dev, proxy through Vite's dev server to avoid CORS:

```ts title="vite.config.ts"
import { defineConfig } from 'vite';

export default defineConfig({
  server: {
    proxy: {
      '/_layers/events': {
        target: 'https://in.layers.com',
        changeOrigin: true,
        rewrite: (p) => p.replace(/^\/_layers\/events/, '/events'),
      },
    },
  },
});
```

Then init with:

```ts
const layers = new LayersClient({
  appId: import.meta.env.VITE_LAYERS_APP_ID,
  baseUrl: import.meta.env.MODE === 'production'
    ? 'https://in.layers.com'
    : 'http://localhost:5173/_layers',
  apiKey: 'unused',
});
```

## SSR with Vite [#ssr-with-vite]

Server-rendered Vite apps (e.g. via `vite-ssr`, Astro's Vite mode) should treat the SDK identically to Next.js — initialize **only** on the client, never on the server. The package gracefully no-ops on a missing `window` in some flows, but the only safe pattern is to gate on `typeof window !== 'undefined'` (or wrap in a client-only component).

## Verifying the install [#verifying-the-install]

```bash
curl -X POST https://api.layers.com/v1/projects/$PROJECT_ID/sdk-apps/$APP_ID/verify-tracking \
  -H "Authorization: Bearer $LAYERS_API_KEY"
```

See [`verify-tracking`](/docs/api/reference/sdk-apps/verify-tracking).

## See also [#see-also]

* [SDK overview](/docs/sdk/overview)
* [Standard events](/docs/sdk/standard-events)
* [Custom domain](/docs/sdk/custom-domain)
* [React Router guide](/docs/sdk/react-router)
* [Server-side forwarding](/docs/api/reference/events/forward)
