Embed Your First Pane¶
This guide walks through every line needed to embed a live cloud data pane in a web page. By the end, you will have a working HTML page that displays EC2 instances from your AWS account.
What you need:
- A linked cloud account (link one here)
- An embed access key (create one here)
The complete example¶
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Infrastructure Status</title>
</head>
<body>
<h1>EC2 Instances</h1>
<!-- 1. Configuration -->
<script>
window.lpEmbed = {
apiBase: 'https://api.lightpane.io',
accessKey: 'csl_em_YOUR_ACCESS_KEY_HERE'
};
</script>
<!-- 2. Loader script — pulls in everything else -->
<script src="https://lightpane.io/embed/lp.js"></script>
<!-- 3. Target div — the pane renders here -->
<div data-lp-service="ec2"
data-lp-region="eu-west-2"
data-lp-attributes="name,instance_id,instance_type,state,private_ip"></div>
</body>
</html>
Replace csl_em_YOUR_ACCESS_KEY_HERE with your embed key. Save the file and open
it in a browser.
What each part does¶
1. Configuration¶
<script>
window.lpEmbed = {
apiBase: 'https://api.lightpane.io',
accessKey: 'csl_em_YOUR_ACCESS_KEY_HERE'
};
</script>
Set this once per page, before the loader script. apiBase is the LightPane
API endpoint; accessKey authenticates your requests. Optional fields you can
add here:
| Field | Purpose |
|---|---|
region |
Default region for every pane on the page (each pane can override via data-lp-region). |
useSession |
Set to true to authenticate via session cookie instead of access key (Hosted Lens flow). |
deferAutoRun |
Set to true to suppress the automatic render on DOMContentLoaded — call window.lpEmbedRun() yourself when ready. |
2. Loader script¶
lp.js is a tiny loader. It injects the underlying CSS and JS modules
(lp-fetch.js, lp-render.js, lp-pane.js, lp-chart.js, sd-embed.js,
sd-embed.css) in the right order, then scans the page for data-lp-service
targets and renders them. You can include it anywhere in the document — <head>,
mid-<body>, or at the end. It picks up panes that exist at DOMContentLoaded;
panes added later require a call to window.lpEmbedRun() to render.
3. Target div¶
<div data-lp-service="ec2"
data-lp-region="eu-west-2"
data-lp-attributes="name,instance_id,instance_type,state,private_ip"></div>
Every pane on the page is one <div> with data-lp-* attributes. The full set:
| Attribute | Purpose |
|---|---|
data-lp-service |
Required. The service to discover. See the Service Catalogue for every supported service. |
data-lp-region |
Cloud region to query. Overrides window.lpEmbed.region. |
data-lp-attributes |
Comma-separated list of attribute IDs to render. Omit to show the service's default columns. |
data-lp-account |
Specific binding alias (e.g. acme-prod-eu) or canonical address (aws:123456789012). Omit to query every binding your key allows. |
data-lp-match |
Substring match against binding aliases — picks every account whose alias contains the string. Mutually exclusive with data-lp-account. |
data-lp-label |
Display title override (e.g. "Production EC2" instead of the default service label). |
data-lp-render |
Render mode override. stacked shows one card per matched binding instead of the default merged table. |
data-lp-source |
Set to mock to render fixture data instead of querying your account — useful for layout previews without a live API hit. |
Multiple <div>s on one page work as expected — each pane renders
independently, and lp.js batches the API calls.
Troubleshooting¶
CORS error in browser console¶
Check that the domain you are serving the page from is listed in the allowed_origins
constraint on your access key. If you are testing locally, add http://localhost:8080
(or your local port) to allowed origins.
401 Unauthorized¶
The access key is invalid, expired, or revoked. Check that:
- The key was copied correctly (no extra spaces or line breaks)
- The key has not expired — check the expiry in Access Keys on your account
- The key has not been revoked
403 Forbidden¶
A constraint check failed. The API response body contains the specific reason:
| Error message | Cause | Fix |
|---|---|---|
| "Origin not permitted for this token" | The page domain is not in allowed_origins |
Add the domain to allowed origins on the key |
| "IP address not permitted for this token" | The client IP is not in allowed_ips |
Update the allowed IPs |
| "Referer header required for this token" | require_referer is enabled but no Referer header was sent |
Serve the page from a web server (not file://) |
| "Service X not permitted by this token" | The key does not include this service | Create a new key with the service included, or use a key scoped to all services |
Pane renders but shows no data¶
The API returned zero resources. This is normal if:
- The region has no resources of that type (e.g. no EC2 instances in
us-west-1) - The cloud account has no resources of that type
Check the browser network tab — the API response will show "resources": [] with
"success": true.
Pane does not render at all¶
Check that:
data-lp-serviceis set on at least one element on the pagewindow.lpEmbed.accessKeyis set beforelp.jsloads (script order matters)lp.jsand its sub-modules are not blocked by Content Security Policy — see the next section- The browser console has no errors from
lp-embed:warnings
Content Security Policy¶
Pages with strict CSP need to allow LightPane's hosts. The minimum policy:
script-src 'self' https://lightpane.io 'unsafe-inline';
style-src 'self' https://lightpane.io 'unsafe-inline';
connect-src 'self' https://api.lightpane.io;
The 'unsafe-inline' requirements come from the inline window.lpEmbed = {...}
block and the runtime style injection in sd-embed.css. If your policy uses
nonces, add a matching nonce to the inline script.