---
title: "Embed"
description: "Mount the same console inside a host app, behind the host's login."
---

The panels `assay dashboard` serves are also a **web component**. A host mounts `<assay-dashboard>`, hands it a client, and gets spend, sessions, timeline, waste, ROI, and pricing inside its own page — behind its own login, in its own theme.

Authentication is always the host's job. The component never fetches on its own paths. It renders whatever the injected client can answer. A panel exists only if the adapter supplies the matching method.

## Smallest mount

A running `assay dashboard` serves a live copy at **`/embed`**. Open it and view source.

```html
<assay-dashboard></assay-dashboard>
<script src="http://127.0.0.1:4319/assets/dashboard.js"></script>
<script>
  const el = document.querySelector('assay-dashboard');
  el.client = AssayDashboard.createRestClient({
    baseUrl: 'http://127.0.0.1:4319',
  });
</script>
```

## Two ways to take the code

| Shape | When |
|---|---|
| ESM `assay/dashboard` | The host already has a bundler |
| Prebuilt script `assay/dashboard/iife` | No bundler, or the app vendors its own copy |

The bundle fetches no font, image, or script. It renders with the network unplugged. The Assay mark is inline. Your CSP needs `img-src data:`.

## What the host must not do

- Do not proxy the loopback console onto the public internet and call that embed. That server has no login.
- Do not expect the component to hide a panel the adapter still implements. Absence of the method hides the panel.
- Do not put the content key in the browser. Decrypt on the server the key already lives on. The key never travels; the console does.

Cross-origin: name the origin. A wildcard origin is refused.

## Snapshot as an alternative

If you need a packet of pages, not a live mount:

```bash
assay dashboard --snapshot ./export
```

See [Dashboard](/dashboard).
