# Quick start


By the end of this guide, the Flare client is running in your Alpine app: it reports errors on its own, and on Alpine 3.15.2 and up each Alpine expression error also carries the expression that failed and the element it ran on.

Alpine has no Flare package of its own. You use `@flareapp/js`, the core browser client, for everything. There is one manual step after you install it: hooking into Alpine's own error handler so a report tells you which expression broke.

## Install and start the client

You need a Flare account and a project key, which you can find on your project's settings page.

The interactive guide below is the fastest way to get started. It fills in your real project key for you when you are logged in, and gives you copy-paste commands to install the package and start the client. Or you can let an AI agent do all the work for you by using the install prompt.

> This guide covers every supported setup. Follow only the steps that match your project: conditional instructions start with a bold "If ..." line describing when they apply. Steps without such a line always apply.
> Install commands use `npm install`. Swap that prefix for the project's own package manager: `yarn add`, `pnpm add`, or `bun add`.
> Replace `PROJECT PUBLIC KEY` with the project's public key. You can find it in the project settings on https://flareapp.io.

## Step 1: Install the package using NPM, Yarn, pnpm, or Bun

**If you don't upload sourcemaps to Flare:**

```shell
npm install @flareapp/js
```

**If you use Vite and upload sourcemaps to Flare:**

```shell
npm install @flareapp/js @flareapp/vite
```

**If you use Webpack and upload sourcemaps to Flare:**

```shell
npm install @flareapp/js @flareapp/webpack
```

**If you use Next.js and upload sourcemaps to Flare:**

```shell
npm install @flareapp/js @flareapp/nextjs
```

## Step 2: Register Flare & configure

Initialize Flare in your `app.js` or `index.js` file:

**If you upload sourcemaps to Flare:**

In `app.js`:

```javascript
import { flare } from "@flareapp/js";

// Only enable Flare in production, we don't want to waste your quota while you're developing:
if (process.env.NODE_ENV === 'production') {
    flare.light();
}
```

**If you don't upload sourcemaps to Flare:**

In `app.js`:

```javascript
import { flare } from "@flareapp/js";

// Only enable Flare in production, we don't want to waste your quota while you're developing:
if (process.env.NODE_ENV === 'production') {
    flare.light('PROJECT PUBLIC KEY');
}
```

**If you enable tracing:**

Tracing shows you where time goes during a page load, a navigation, and the requests your page makes. Add this inside the same production check, after `flare.light()`. Read more in [how tracing works](/docs/javascript/tracing/how-tracing-works) and [sampling](/docs/javascript/tracing/sampling).

In `app.js`:

```javascript
flare.configure({
    enableTracing: true,
    // Sends 10% of traces. Raise it for more detail, lower it to save quota.
    tracesSampleRate: 0.1,
});
```

**If you use Vite and upload sourcemaps to Flare:**

Configure Vite to upload sourcemaps to Flare:

In `vite.config.js`:

```javascript
import { defineConfig } from 'vite';
import flareSourcemaps from '@flareapp/vite';

export default defineConfig({
    plugins: [
        flareSourcemaps({
            apiKey: 'PROJECT PUBLIC KEY'
        }),
    ],
});
```

**If you use Webpack and upload sourcemaps to Flare:**

Configure Webpack to upload sourcemaps to Flare:

In `webpack.config.js`:

```javascript
const { FlareWebpackPlugin } = require("@flareapp/webpack");

module.exports = {
    // ...
    devtool: "source-map",
    plugins: [ new FlareWebpackPlugin({ apiKey: "PROJECT PUBLIC KEY" }) ],
};
```

**If you use Next.js and upload sourcemaps to Flare:**

Wrap your Next.js config with `withFlareSourcemaps` in `next.config.mjs`:

In `next.config.mjs`:

```javascript
import { withFlareSourcemaps } from '@flareapp/nextjs';

export default withFlareSourcemaps({
    // your normal Next.js config
}, {
    apiKey: 'PROJECT PUBLIC KEY',
});
```

## Step 3: Connect your project key

**If you upload sourcemaps to Flare:**

When you install Flare's sourcemap build plugin, the build plugin injects your public key so `flare.light()` can run without an explicit key. Make sure you add the domains of your application in the project settings on Flare.

**If you don't upload sourcemaps to Flare:**

Pass your public key directly to `flare.light('PROJECT PUBLIC KEY')` and make sure you add the domains of your application in the project settings on Flare.

## Step 4: Verify your setup

Add this code temporarily to verify everything is working:

In `app.js`:

```javascript
flare.test();
```

**If you use Vite and upload sourcemaps to Flare:**

Run your Vite build command. You should see the following lines in the output:

```shell
@flareapp/vite: Uploading xx sourcemap(s) to Flare.
@flareapp/vite: Successfully uploaded all sourcemaps to Flare.
```

**If you use Next.js and upload sourcemaps to Flare:**

Run `next build`. You should see the following lines in the output:

```shell
@flareapp/webpack: Uploading 4 sourcemap(s) to Flare.
@flareapp/webpack: Successfully uploaded all sourcemaps to Flare.
```

Prefer to install and configure the client by hand, or not logged in? Install the package:

```bash tab=npm
npm install @flareapp/js
```

```bash tab=yarn
yarn add @flareapp/js
```

```bash tab=pnpm
pnpm add @flareapp/js
```

```bash tab=bun
bun add @flareapp/js
```

Then add this near the top of your application's entry file, before any other code runs, so the client can catch errors as early as possible:

```js
import { flare } from '@flareapp/js';

if (process.env.NODE_ENV === 'production') {
    flare.light('YOUR PROJECT KEY');
}
```

The guard keeps the client off during local development, so you don't use up your quota while you work.

`flare.light()` switches on the client's automatic error listeners. That is all you need for the next step to work: the manual Alpine step below adds context, it is not what turns reporting on.

## Alpine errors are already caught

When an expression in an Alpine directive throws, for example in `x-init`, `x-on:click`, or `x-text`, Alpine logs it to the console and re-throws it as an uncaught error. The Flare client already listens for uncaught errors, so once you have called `flare.light()`, those errors are sent to Flare with no extra code.

This works on every version of Alpine. What you don't get for free is *which* Alpine expression broke, or on *which* element. The next step adds that.

## Add the expression that failed

Alpine 3.15.2 added `Alpine.setErrorHandler()`, a single place to handle every error thrown in an Alpine expression. Its callback receives the error, the element the expression ran on, and the expression itself. Report the error from there and you get all three in Flare.

Register the handler where you start Alpine:

```js
import { flare, convertToError, toCustomContext } from '@flareapp/js';
import Alpine from 'alpinejs';

flare.setFramework({ name: 'alpine' });

if (Alpine.setErrorHandler) {
    Alpine.setErrorHandler(reportAlpineError);
}

window.Alpine = Alpine;
Alpine.start();
```

`reportAlpineError` is the shared handler below. The `if` around it is on purpose: on Alpine older than 3.15.2 `setErrorHandler` is missing, so the check skips it and you keep the automatic capture from the step above.

Define the handler once and reuse it:

```js
function reportAlpineError(error, el, expression) {
    const errorToReport = convertToError(error);

    flare.reportSilently(errorToReport, toCustomContext('alpine', {
        expression,
        element: describeElement(el),
    }));

    // Alpine's own handler does this; keep it so the error still shows in the console.
    console.warn(`Alpine Expression Error: ${errorToReport.message}`, el);
}

function describeElement(el) {
    if (! el) {
        return null;
    }

    return {
        tag: el.tagName.toLowerCase(),
        id: el.id || undefined,
        classes: [...el.classList],
        directives: [...el.attributes]
            .map((attribute) => attribute.name)
            .filter((name) => name.startsWith('x-') || name.startsWith('@') || name.startsWith(':')),
    };
}
```

Two things to know about this handler:

- **`setErrorHandler` replaces Alpine's default handler, it does not add to it.** Alpine's default logs a warning and re-throws the error. Your handler runs instead, so the `console.warn` above is there to keep the console message you would otherwise lose.
- **Don't re-throw the error.** You now report it yourself. Re-throwing it as well would also hand it to the browser's error event, which the Flare client is already listening on, and the same error would arrive in Flare twice. The client does not de-duplicate reports.

`describeElement` sends a small, safe description of the element: its tag, id, classes, and the names of its Alpine directives. It does not send the element's HTML, so bound values, which can hold user data, stay out of your reports. If you want the full element instead, and you accept that trade-off, send `el.outerHTML` instead.

> Alpine's error handler is not on its documentation site. The source of truth is the [v3.15.2 release](https://github.com/alpinejs/alpine/releases/tag/v3.15.2) and [the pull request that added it](https://github.com/alpinejs/alpine/pull/4673).

## Livewire

Livewire 3 ships with Alpine, so the same handler works. You only register it in a different place, because Livewire starts Alpine for you.

With a standard Livewire setup, Livewire starts Alpine itself. Register your handler inside the `alpine:init` event, which fires before Alpine starts:

```js
import { flare, convertToError, toCustomContext } from '@flareapp/js';

document.addEventListener('alpine:init', () => {
    flare.setFramework({ name: 'alpine' });

    if (window.Alpine.setErrorHandler) {
        window.Alpine.setErrorHandler(reportAlpineError);
    }
});
```

If you build Livewire's assets yourself, import Alpine from Livewire's bundle and register the handler before you call `Livewire.start()`:

```js
import { Livewire, Alpine } from '../../vendor/livewire/livewire/dist/livewire.esm';

flare.setFramework({ name: 'alpine' });

if (Alpine.setErrorHandler) {
    Alpine.setErrorHandler(reportAlpineError);
}

Livewire.start();
```

Use the same `reportAlpineError` and `describeElement` functions from the step above. Livewire pins its own Alpine version, so `setErrorHandler` is only there once its bundled Alpine is 3.15.2 or newer. The `if` guard covers that: on an older Livewire you keep the automatic capture, and upgrade Livewire when you want the extra context.

This step is about errors in your browser. Errors on the server, in your Livewire components' PHP, are reported by the Laravel client instead. See [Livewire](/docs/laravel/data-collection/livewire) in the Laravel docs.

## Check that errors arrive

Add a button that throws from an Alpine expression, so the handler actually runs:

```html
@verbatim
<button x-data @click="throw new Error('My first Flare error')">
    Break Alpine
</button>
@endverbatim
```

Click it, then open your project in Flare. The error shows up within a few seconds, with its message, a stack trace, and the browser it came from. On Alpine 3.15.2 and up it also carries the expression and the element under custom context. Remove the button once you have confirmed it arrived.

## See your real source code

If you bundle your code for production, the stack trace above points at minified, bundled output instead of the file and line you actually wrote. Fix that by uploading a sourcemap after every build, using the Vite or Webpack plugin. Follow [see your real source code](/docs/javascript/getting-started/quick-start#see-your-real-source-code) in the JavaScript quick start for the install and config steps.

## Next steps

- [Reporting errors](/docs/javascript/errors/reporting-errors): report caught errors and send log messages by hand.
- [Client hooks](/docs/javascript/errors/client-hooks): change or drop a report before it's sent.
- [Sourcemaps](/docs/javascript/errors/sourcemaps): sourcemaps for Vite, Webpack, Laravel Mix, and manual uploads.
- [Adding custom context](/docs/javascript/data-collection/adding-custom-context) and [identifying users](/docs/javascript/data-collection/identifying-users).
- [How tracing works](/docs/javascript/tracing/how-tracing-works), [manual spans](/docs/javascript/tracing/manual-spans), and [sampling](/docs/javascript/tracing/sampling).
- [API reference](/docs/javascript/reference/api) and [configuration reference](/docs/javascript/reference/configuration).
