Skip to content

Embed in a Web Page

This guide covers embedding panes beyond the basics. If you have not embedded a pane before, start with Embed Your First Pane.

Multiple services on one page

Add a service request and target div for each service you want to display. All requests are sent in a single batch API call.

multi-service.html
<!-- Access key (once per page) -->
<script>
    var serviceDiscoveryConfig = {
        accessKey: 'csl_em_YOUR_ACCESS_KEY_HERE'
    };
</script>

<!-- EC2 instances -->
<script>
    var serviceDiscoveryRequests = serviceDiscoveryRequests || [];
    serviceDiscoveryRequests.push({
        service: 'ec2',
        provider: 'aws',
        region: 'eu-west-2',
        source: 'live',
        attributes: ['name', 'instance_id', 'instance_type', 'state', 'private_ip']
    });
</script>

<h2>EC2 Instances</h2>
<div data-sd-service="ec2" data-sd-source="live"></div>

<!-- S3 buckets -->
<script>
    serviceDiscoveryRequests.push({
        service: 's3',
        provider: 'aws',
        region: 'eu-west-2',
        source: 'live',
        attributes: ['bucket_name', 'creation_date', 'region']
    });
</script>

<h2>S3 Buckets</h2>
<div data-sd-service="s3" data-sd-source="live"></div>

<!-- Lambda functions -->
<script>
    serviceDiscoveryRequests.push({
        service: 'lambda_functions',
        provider: 'aws',
        region: 'eu-west-2',
        source: 'live',
        attributes: ['name', 'runtime', 'memory', 'timeout', 'last_modified']
    });
</script>

<h2>Lambda Functions</h2>
<div data-sd-service="lambda_functions" data-sd-source="live"></div>

<!-- SDK scripts (once, at end of page) -->
<script src="https://cdn.lightpane.cloud/sdk/v1/sd-core.js"></script>
<script src="https://cdn.lightpane.cloud/sdk/v1/sd-fetch.js"></script>
<script src="https://cdn.lightpane.cloud/sdk/v1/sd-render.js"></script>
<script src="https://cdn.lightpane.cloud/sdk/v1/sd-format.js"></script>
<script src="https://cdn.lightpane.cloud/sdk/v1/sd-boot.js"></script>

The SDK batches all requests into a single API call. Each response is matched to its target div by the data-sd-service attribute.

Choose which columns to display

The attributes array controls which columns appear in the rendered table. Omit attributes entirely to show all available columns for that service.

// Show only name and state
serviceDiscoveryRequests.push({
    service: 'ec2',
    provider: 'aws',
    region: 'eu-west-2',
    source: 'live',
    attributes: ['name', 'state']
});
// Show all available columns
serviceDiscoveryRequests.push({
    service: 'ec2',
    provider: 'aws',
    region: 'eu-west-2',
    source: 'live'
});

See the Service Catalogue for the full list of available attributes per service.

Multiple regions

Add separate requests for each region. Use different target divs.

<script>
    serviceDiscoveryRequests.push({
        service: 'ec2',
        provider: 'aws',
        region: 'eu-west-2',
        source: 'live',
        attributes: ['name', 'instance_id', 'state']
    });
    serviceDiscoveryRequests.push({
        service: 'ec2',
        provider: 'aws',
        region: 'us-east-1',
        source: 'live',
        attributes: ['name', 'instance_id', 'state']
    });
</script>

<h2>EU West 2</h2>
<div data-sd-service="ec2" data-sd-source="live" data-sd-region="eu-west-2"></div>

<h2>US East 1</h2>
<div data-sd-service="ec2" data-sd-source="live" data-sd-region="us-east-1"></div>

Multiple cloud providers

Mix AWS and GCP services on the same page. The SDK handles routing each request to the correct provider.

<script>
    serviceDiscoveryRequests.push({
        service: 'ec2',
        provider: 'aws',
        region: 'eu-west-2',
        source: 'live',
        attributes: ['name', 'instance_id', 'instance_type', 'state']
    });
    serviceDiscoveryRequests.push({
        service: 'compute_instances',
        provider: 'gcp',
        region: 'europe-west2',
        source: 'live',
        attributes: ['name', 'machine_type', 'status', 'zone']
    });
</script>

<h2>AWS EC2 Instances</h2>
<div data-sd-service="ec2" data-sd-source="live"></div>

<h2>GCP Compute Instances</h2>
<div data-sd-service="compute_instances" data-sd-source="live"></div>

Batch request limits

If your access key has a max_batch_size constraint, the SDK splits requests into batches automatically. A key with max_batch_size: 5 and 12 service requests will make 3 API calls (5 + 5 + 2).

For pages with many services, increase the max_batch_size on your access key or remove the constraint entirely.

Page layout with Bootstrap

Pane components do not require Bootstrap, but you can use Bootstrap's grid to arrange panes side by side.

<link rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
<link rel="stylesheet"
      href="https://cdn.lightpane.cloud/sdk/v1/clouds-and-light.css">

<div class="container mt-4">
    <div class="row">
        <div class="col-md-6">
            <h3>EC2 Instances</h3>
            <div data-sd-service="ec2" data-sd-source="live"></div>
        </div>
        <div class="col-md-6">
            <h3>S3 Buckets</h3>
            <div data-sd-service="s3" data-sd-source="live"></div>
        </div>
    </div>
</div>

Refreshing data

Panes load data once when the page loads. To refresh without a full page reload, call the SDK's refresh function:

// Refresh all panes on the page
if (window.serviceDiscoveryRefresh) {
    window.serviceDiscoveryRefresh();
}

You can wire this to a button:

<button onclick="window.serviceDiscoveryRefresh()">Refresh</button>

CORS and access key setup

For embedded pages, your access key needs:

  • allowed_origins set to the domain(s) where the page is hosted
  • Type set to embed

If you are developing locally, add your local URL (e.g. http://localhost:3000) to allowed_origins during development. Remove it before deploying.

Testing locally

Serve the page from a local web server rather than opening the HTML file directly. The file:// protocol does not send Origin headers, which causes constraint validation to fail.

python3 -m http.server 8080