# Installation (/docs/javascript/installation)

Tracepanel for JavaScript is the `@tracepanel/js` package. It records the
traces of your Node.js or Bun app and sends them to the agent.

The current version is 0.2.0, the same as the agent's. `npm install
@tracepanel/js` installs the agent of the same version. See the
[changelog](https://github.com/tracepanel/tracepanel-js/blob/main/CHANGELOG.md).

## Install the package [#install-the-package]

```bash
npm install @tracepanel/js
```

The package also installs `@tracepanel/agent`, the program that stores the
traces and serves the console. You don't install or start it yourself. See
[How it works](/docs/how-it-works). It brings OpenTelemetry's instrumentations
with it, so there is nothing else to install.

## Add it to your app [#add-it-to-your-app]

Tracepanel loads before your app, so it can hook the HTTP server, the
framework and the database driver as they load. Each framework gets it in
its own way.

<Tabs items={["Express", "NestJS", "Next.js", "Nuxt", "Bun"]}>
  <Tab value="Express">

Start the app with Tracepanel loaded before it:

```bash
node --import @tracepanel/js/register server.js
```

Add the middleware. It puts the badge on HTML pages and gives every response
its trace's headers:

```js
import express from "express";
import { tracepanel } from "@tracepanel/js/express";

const app = express();
app.use(tracepanel());
```

Tracepanel supports Express 4.18 and newer.

  </Tab>
  <Tab value="NestJS">

Nest runs on Express. Load Tracepanel the same way, and add the same
middleware in `main.ts`:

```bash
node --import @tracepanel/js/register dist/main.js
```

```ts
import { NestFactory } from "@nestjs/core";
import { tracepanel } from "@tracepanel/js/express";
import { AppModule } from "./app.module.js";

const app = await NestFactory.create(AppModule);
app.use(tracepanel());
await app.listen(3000);
```

Each request's handler is its controller method, such as
`BooksController.list`. The records of Nest's `Logger` go to the request's
trace. An `HttpException` that answers with a status below 500 is the
response, not an error.

  </Tab>
  <Tab value="Next.js">

Next.js starts its own server, so Tracepanel goes in from the instrumentation
hook:

```ts
// instrumentation.ts
export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") (await import("@tracepanel/js/next")).register();
}
```

Keep the package out of the bundles:

```ts
// next.config.ts
const config = { serverExternalPackages: ["@tracepanel/js"] };
export default config;
```

Put the badge in the root layout:

```tsx
// app/layout.tsx
import { Tracepanel } from "@tracepanel/js/next/widget";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <Tracepanel />
      </head>
      <body>{children}</body>
    </html>
  );
}
```

Next.js makes each request's root span itself. A request's handler is its
page or route handler, named by its route, such as `/api/books/[id]`.

  </Tab>
  <Tab value="Nuxt">

Add the module:

```ts
// nuxt.config.ts
export default defineNuxtConfig({ modules: ["@tracepanel/js/nuxt"] });
```

Start `nuxt dev` with Tracepanel loaded, so it hooks the database driver as
Nitro loads it:

```bash
NODE_OPTIONS=--import=@tracepanel/js/register nuxt dev
```

The module names each request by its route, such as `/api/books/:id`. It puts
the badge on server-rendered pages and records the errors h3 answers with a
500.

  </Tab>
  <Tab value="Bun">

Start the app with Tracepanel preloaded:

```bash
bun --preload @tracepanel/js/register server.ts
```

`serve()` is `Bun.serve` with each route traced under its pattern:

```ts
import { serve } from "@tracepanel/js/bun";

serve({
  routes: {
    "/api/books/:id": async (req) => Response.json(await findBook(req.params.id)),
  },
});
```

`withTracepanel()` wraps any fetch handler instead, such as Hono's
`app.fetch`.

  </Tab>
</Tabs>

Tracepanel is on unless `NODE_ENV` is `production`. Open a page of your app
and click the badge in the corner. The first request starts the agent, and
the console is at `/__tracepanel__/` on your app.

For a single-page app on Vite's dev server, add the Vite plugin. See
[Pages in the browser](/docs/javascript/browser).

## Start without the flag [#start-without-the-flag]

The `--import` flag is how Tracepanel gets in before your app. An ES module's
imports all load before any of its code runs, so `import
"@tracepanel/js/register"` at the top of `server.js` comes too late for
Express and the database driver.

Without the flag, let the `tracepanel` command add it:

```json
{ "scripts": { "dev": "tracepanel run node server.js" } }
```

Or start from a file that loads Tracepanel, then imports your app:

```js
// main.js, run with `node main.js`
import "@tracepanel/js/register";
await import("./server.js");
```

The agent starts by itself either way, on the app's first request.

## Supported versions [#supported-versions]

Tracepanel for JavaScript runs on Node.js 20.19 and newer, and on Bun. See
[Integrations](/docs/javascript/integrations) for the frameworks and
libraries it records.

The agent comes for the same platforms as with Python:

- Linux on glibc: x86_64, arm64, armv7, i686, ppc64le, s390x and riscv64.
- Linux on musl, such as Alpine: x86_64, arm64, armv7, armv6 and i686.
- macOS: Apple silicon and Intel.
- Windows: x86_64, x86 and arm64.

Keep `.tracepanel/` out of your repository:

```bash
echo ".tracepanel/" >> .gitignore
```
