Sample app for Modular embedding in Metabase. See the full SDK demo for what's possible. This app provides a minimal setup to understand each approach (you'll need to bring your own Metabase).
- Metabase Pro or Enterprise (free trial)
- Bun
Admin > Settings > Embedding > Enable Modular embedding
| Embed Type | Where to find the key |
|---|---|
| SSO + SDK | Admin > Settings > Authentication > JWT > JWT signing key |
| Guest | Admin > Settings > Embedding > Embedding secret key |
Run:
cp .env-template .env
Then edit your .env :
METABASE_SECRET_KEY="your-jwt-signing-key"
METABASE_EMBEDDING_SECRET_KEY="your-embedding-secret-key"
METABASE_SITE_URL="http://localhost:3000"
In Metabase (Admin > Settings > Authentication > JWT):
- Set JWT Identity Provider URI to
http://localhost:8080/sso/metabase. - Ensure the signing key matches
METABASE_SECRET_KEY.
Admin > Settings > Embedding > Security > Authorized origins.
Add http://localhost:8080 (though localhost should be enabled by default).
Install with:
bun install
Run with:
bun run start
Open http://localhost:8080 to view the app. Use the tabs to switch between the different types of embeds.
| Method | Auth | Use case |
|---|---|---|
| Guest Embed | Signed JWT | Anonymous view-only, locked to specific items |
| SSO Embed | JWT SSO (user identity) | Personalized dashboards, full Metabase features |
| React SDK | JWT SSO (user identity) | SSO features + plugins and custom actions |
├── index.ts # Server with auth endpoints
├── src/sdk-app.tsx # React SDK app
├── public/
│ ├── index.html # SSO Embed
│ ├── guest.html # Guest Embed
│ ├── sdk.html # React SDK
│ ├── theme-common.js # Shared theme panel UI
│ ├── theme.js # SSO config
│ └── guest-theme.js # Guest config
GET /sso/metabase- JWT token for SSO/SDK (authenticated users)GET /api/metabase/guest-token- Signed token for guest embedding
Browser → embed.js → /sso/metabase → JWT with user claims → Metabase
The <metabase-dashboard> component uses authProviderUri to fetch a JWT containing user info (email, name). Metabase auto-provisions the user on first login.
<metabase-dashboard dashboard-id="1" with-title="false"></metabase-dashboard>window.metabaseConfig = {
instanceUrl: "http://localhost:3000",
authProviderUri: "http://localhost:8080/sso/metabase",
};Browser → /api/metabase/guest-token → JWT with resource access → embed.js → Metabase
The token grants access to a specific dashboard without user identity. Your server signs tokens with the embedding secret key.
<metabase-dashboard
with-title="true"
with-downloads="true"
></metabase-dashboard>window.metabaseConfig = {
isGuest: true,
instanceUrl: "http://localhost:3000",
};
// Fetch token from your backend, then:
dashboard.setAttribute("token", token);Browser → React app → fetchRequestToken → JWT with user claims → Metabase
The SDK provides React components with full interactivity. Uses the same JWT SSO auth as SSO Embed, but adds support for plugins and custom actions.
import {
MetabaseProvider,
InteractiveDashboard,
defineMetabaseAuthConfig,
} from "@metabase/embedding-sdk-react";
const authConfig = defineMetabaseAuthConfig({
metabaseInstanceUrl: "http://localhost:3000",
fetchRequestToken: async () => {
const response = await fetch("/sso/metabase");
return await response.json();
},
});
function App() {
return (
<MetabaseProvider authConfig={authConfig}>
<InteractiveDashboard dashboardId={1} withTitle withDownloads />
</MetabaseProvider>
);
}The SDK also supports plugins for custom click actions:
const pluginsConfig = {
mapQuestionClickActions: (clickActions, clicked) => [
...clickActions,
{
name: "custom-action",
title: "Custom action",
icon: "star",
onClick: ({ closePopover }) => {
alert(`Clicked: ${clicked?.value}`);
closePopover?.();
},
},
],
};
<MetabaseProvider authConfig={authConfig} pluginsConfig={pluginsConfig}>
...
</MetabaseProvider>;Edit the dashboard-id attribute (SSO) or resource.dashboard in the token payload (Guest).
Edit the JWT claims in index.ts:
const token = jwt.sign(
{
email: "[email protected]",
first_name: "First",
last_name: "Last",
exp: Math.floor(Date.now() / 1000) + 60 * 10,
},
METABASE_SECRET_KEY,
);Click the Theme button to customize colors. Click Export theme to download as JSON.
| Issue | Solution |
|---|---|
| CORS errors | Add http://localhost:8080 to allowed origins in Metabase |
| "Message corrupted" (Guest) | Check METABASE_EMBEDDING_SECRET_KEY matches Metabase |
| JWT errors (SSO) | Check METABASE_SECRET_KEY matches Metabase |
| Dashboard not found | Verify dashboard ID exists and user has access |
bun run build # Build SDK bundle only
bun run dev # Run server (after build)
bun run start # Build and run