> For the complete documentation index, see [llms.txt](https://docs.sealights.io/knowledgebase/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sealights.io/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/node.js-agent/capturing-runtime-coverage/frontend-instrumentation-static.md).

# Frontend Instrumentation (static)

> **Applies to:** frontend applications — Angular, React, Vue, and other bundled JavaScript apps.

Frontend apps use **static instrumentation**. The `instrument` command rewrites your built bundle and adds SeaLights coverage hooks before deployment.

You then deploy that instrumented copy to a test environment. As tests exercise the UI, the app reports coverage.

This is different from [Scanning Your Application](/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/node.js-agent/scanning-your-application.md). `scan` uploads the build map. `instrument` rewrites the deployable files.

{% stepper %}
{% step %}

### Scan the frontend build

Start by scanning the built bundle. This creates the SeaLights build map.

You need a valid token and Build Session ID first. See [Scanning Your Application → Prerequisites](/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/node.js-agent/scanning-your-application.md#prerequisites) and [Scanning a frontend build](/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/node.js-agent/scanning-your-application.md#scanning-a-frontend-build-bundled).
{% endstep %}

{% step %}

### Instrument the build

Run `instrument` on the built bundle, usually `dist`.

The command writes an instrumented copy to `sl_dist`.

#### Command syntax

{% tabs %}
{% tab title="Bash" %}

```sh
npx slnodejs instrument \
  --tokenFile ./sltoken.txt \
  --buildSessionIdFile buildSessionId \
  --scanDir dist \
  --outputPath sl_dist \
  --labId <Lab ID> \
  --splitPreambleIntoFile \
  --failOnError
```

{% endtab %}

{% tab title="GitHub Actions" %}

```yaml
- name: SeaLights instrument (frontend)
  run: |
    npx slnodejs instrument \
      --token "${{ secrets.SL_TOKEN }}" \
      --buildSessionIdFile buildSessionId \
      --scanDir dist \
      --outputPath sl_dist \
      --splitPreambleIntoFile \
      --failOnError
```

{% endtab %}

{% tab title="PowerShell" %}

```powershell
npx slnodejs instrument `
  --tokenFile .\sltoken.txt `
  --buildSessionIdFile buildSessionId `
  --scanDir dist `
  --outputPath sl_dist `
  --labId <Lab ID> `
  --splitPreambleIntoFile `
  --failOnError
```

{% endtab %}

{% tab title="Azure DevOps" %}

```yaml
- script: |
    npx slnodejs instrument \
      --token "$(SL_TOKEN)" \
      --buildSessionIdFile buildSessionId \
      --scanDir dist \
      --outputPath sl_dist \
      --splitPreambleIntoFile \
      --failOnError
  displayName: SeaLights instrument (frontend)
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
**Important Notes:**

* **Never deploy instrumented code to production.** `sl_dist` is for test environments only.
* If your app sends **CSP** headers, they can block the SeaLights scripts. Whitelist the SeaLights endpoints or use `--splitPreambleIntoFile` to serve the preamble from your own origin.
  {% endhint %}

{% hint style="info" %}
If you omit `--labId`, SeaLights uses the Build Session ID as the Lab ID.
{% endhint %}
{% endstep %}

{% step %}

### Deploy the instrumented output

`instrument` creates an `sl_dist` folder that mirrors `dist`, with SeaLights coverage hooks added to the JavaScript files.

#### Basic deployment

The simplest approach is to swap `sl_dist` into the original location. Your web server config stays unchanged.

{% tabs %}
{% tab title="Bash" %}

```sh
mv dist dist_original
mv sl_dist dist
# Alternative: symbolic link (avoids renaming back later)
# ln -s sl_dist dist
```

{% endtab %}

{% tab title="GitHub Actions" %}

```yaml
- name: Deploy instrumented build (swap)
  run: |
    mv dist dist_original
    mv sl_dist dist
    # Then deploy the dist folder to your test environment
```

{% endtab %}

{% tab title="PowerShell" %}

```powershell
Rename-Item dist dist_original
Rename-Item sl_dist dist
```

{% endtab %}

{% tab title="Azure DevOps" %}

```yaml
- script: |
    mv dist dist_original
    mv sl_dist dist
  displayName: Swap instrumented build into place
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
After testing, restore the original (`mv dist_original dist`) or deploy from a clean build rather than the instrumented one for production.
{% endhint %}

<details>

<summary>Multiple environments</summary>

If several test environments need separate coverage, use a different Lab ID for each one.

{% hint style="info" %}
Use **Option A** for a small number of environments. Use **Option B** when repeated instrumentation is too slow.
{% endhint %}

**Option A — run `instrument` in each environment**

This is the most common setup.

Scan the build once in CI. Deploy the original scanned `dist` to each test environment. Then run `instrument` in that environment with its own Lab ID and `--outputPath`.

```sh
npx slnodejs instrument --tokenFile ./sltoken.txt --buildSessionIdFile buildSessionId \
  --scanDir dist --outputPath sl_dist_env1 --labId lab_env1 --splitPreambleIntoFile

npx slnodejs instrument --tokenFile ./sltoken.txt --buildSessionIdFile buildSessionId \
  --scanDir dist --outputPath sl_dist_env2 --labId lab_env2 --splitPreambleIntoFile
```

Each environment then serves its own instrumented output.

**Option B — instrument once and replace the Lab ID**

Instrument with a placeholder Lab ID, then replace it in each deployment copy.

```sh
# Instrument once with a placeholder
npx slnodejs instrument --tokenFile ./sltoken.txt --buildSessionIdFile buildSessionId \
  --scanDir dist --outputPath sl_dist --labId "LAB_PLACEHOLDER" --splitPreambleIntoFile

# For each environment, copy sl_dist and replace the placeholder
cp -r sl_dist sl_dist_env1
find sl_dist_env1 -name "*.js" -exec sed -i 's/LAB_PLACEHOLDER/lab_env1/g' {} \;

cp -r sl_dist sl_dist_env2
find sl_dist_env2 -name "*.js" -exec sed -i 's/LAB_PLACEHOLDER/lab_env2/g' {} \;
```

</details>

#### Validate the result

After deployment, open the app in a browser and check:

1. Open **Developer Tools → Sources**.
2. Check your main bundle for the SeaLights preamble and `SL` initialization code.
3. Confirm the build data matches the build you scanned.

If the preamble is missing, the instrumented build was not deployed or was overwritten later.
{% endstep %}

{% step %}

### Run your tests

Once the instrumented build is deployed, continue to [Capturing Tests](/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/node.js-agent/capturing-tests.md).
{% endstep %}
{% endstepper %}

### Extra information

#### Parameters

| Parameter                                   | Purpose                                                                                    |
| ------------------------------------------- | ------------------------------------------------------------------------------------------ |
| `--tokenFile` / `--token`                   | SeaLights authentication (file locally, secret in CI)                                      |
| `--buildSessionIdFile` / `--buildSessionId` | Build session identifier                                                                   |
| `--scanDir`                                 | The built bundle to instrument, usually `dist`                                             |
| `--outputPath`                              | Where to write the instrumented copy, usually `sl_dist`                                    |
| `--labId`                                   | Connects this build to a test lab. If omitted, the Build Session ID is used as the Lab ID. |
| `--splitPreambleIntoFile`                   | Writes the SeaLights preamble to a separate file for CSP or caching scenarios              |
| `--failOnError`                             | Fails the build step if instrumentation errors occur                                       |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.sealights.io/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/node.js-agent/capturing-runtime-coverage/frontend-instrumentation-static.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
