Inline embed quickstart
The inline embed mounts a dashboard directly into your page and returns a JavaScript handle. Authentication starts on your server; rendering happens in the browser inside a shadow root.
1. Create a token endpoint
Your backend exchanges a Ridge API key for a dashboard-scoped JWT. Never send the API key to the browser.
// Your server, after authenticating the current user.
const response = await fetch("https://app.ridgedata.ai/api/embed/token", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.RIDGE_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ dashboardIds: ["dashboard-id-123"] })
});
if (!response.ok) throw new Error("Could not create a Ridge embed token");
const { token } = await response.json();
// Return only `token` from your own authenticated endpoint.See Inline authentication for the full credential flow and Partitioning before adding row-level restrictions.
2. Add a container and the loader
Load ridgeEmbedLoader.js from Ridge. The loader fetches the authenticated bundle and mounts it into a shadow root. This endpoint needs no credentials — the loader is what obtains the token-protected bundle, so it has to load before your JWT exists.
<div id="ridge-dashboard" style="min-height: 400px"></div>
<script src="https://app.ridgedata.ai/api/embed/loader"></script>That serves the current loader. To pin a release instead, add ?v=:
<script src="https://app.ridgedata.ai/api/embed/loader?v=1.2.3"></script>Pinned versions are immutable and cached for a year; the unpinned URL revalidates hourly, so fixes reach your page without a redeploy.
The loader is also a valid ES module if you prefer an explicit import, or if you would rather vendor the file into your own static assets:
<script type="module">
import { RidgeEmbed } from "https://app.ridgedata.ai/api/embed/loader";
</script>Either form gives you the same RidgeEmbed object; the plain <script> tag above also sets it on window.
3. Fetch a JWT and mount
<script type="module">
const tokenResponse = await fetch("/api/ridge-token", { credentials: "same-origin" });
if (!tokenResponse.ok) throw new Error("Could not authorize dashboard");
const { token } = await tokenResponse.json();
const ridge = await window.RidgeEmbed.load({
jwt: token,
dashboardId: "dashboard-id-123",
rootElementId: "ridge-dashboard"
});
ridge.on("statechange", ({ state }) => console.log(state));
await ridge.ready;
console.log(ridge.getState());
</script>load() resolves after the bundle has loaded and returns a stable handle. Attach listeners immediately, then await ridge.ready before synchronous reads. Writes wait for readiness internally.
Loader options
| Option | Required | Description |
|---|---|---|
jwt | yes | JWT returned by your backend. |
dashboardId | yes | Published dashboard to render. |
rootElementId | yes | Container element id. |
apiBaseUrl | no | Defaults to https://app.ridgedata.ai. |
theme | no | Per-mount overrides; see Theming. |
state | no | Initial component state. |
onError | no | Called when the dashboard cannot load. |
Cleanup
Call ridge.unmount() when a SPA removes the dashboard. This stops its listeners and queries rather than leaving them attached to a discarded route.