skills/metabase-react-sdk-setup/SKILL.md
First-time setup for the Metabase React SDK — instance detection, API key, dashboard discovery, JWT auth, SDK installation, and initial embedding code.
npx skillsauth add metabase/agent-skills metabase-react-sdk-setupInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill for any task involving @metabase/embedding-sdk-react — whether that's initial setup, embedding dashboards, theming, or plugins.
Communication style: Be concise. Do one step at a time. When asking the user for input, output only the question — do not explain upcoming steps, implementation details, or what you plan to do next. The user does not need a roadmap.
CRITICAL — YOU MUST GET AN API KEY BEFORE DOING ANYTHING ELSE
Step 1 asks the user for a Metabase URL and API key. You CANNOT proceed without both. Do NOT detect the Metabase version, fetch
llms.txt, install packages, or write ANY code until the user has given you an API key. Do NOT attempt to call any Metabase API endpoint without an API key — it will return 401 and you will be guessing. If any Metabase API call returns 401, STOP everything and ask the user for an API key.
You need a Metabase instance URL and an admin API key before anything else.
.env.metabase is only for admin tasks within this skill (API calls to Metabase). It is NOT the app's runtime config. Never import, read, or reference .env.metabase from the user's application code or build config. The app's instance URL goes in the user's own .env file (e.g., VITE_METABASE_URL, NEXT_PUBLIC_METABASE_URL) — set that up in Step 4.
Check if .env.metabase exists in the project root and already has both METABASE_INSTANCE_URL (non-empty) and METABASE_ADMIN_API_KEY (non-empty). If so, skip to Step 2.
Otherwise, create the file and gitignore it:
grep -qxF '.env.metabase' .gitignore 2>/dev/null || echo '.env.metabase' >> .gitignore
printf 'METABASE_INSTANCE_URL=\nMETABASE_ADMIN_API_KEY=\n' > .env.metabase
Then output only this message — no preamble, no explanation of what comes next, no implementation details:
I created
.env.metabasein the project root. Please fill in both values:
- Set
METABASE_INSTANCE_URLto your Metabase URL (e.g.http://localhost:3000)- Open
{your URL}/admin/settings/authentication/api-keys, create a new API key- Set
METABASE_ADMIN_API_KEYto that key- Let me know when you're done
Do not guess or assume the instance URL. Do not pre-fill localhost:3000. Do not ask the user to paste the key in the chat — it should only go in .env.metabase. Wait for the user to confirm, then proceed to Step 2.
Now that you have an API key, detect the version and find dashboards.
source .env.metabase && \
curl -s "$METABASE_INSTANCE_URL/api/session/properties" \
-H "X-API-Key: $METABASE_ADMIN_API_KEY" | grep -o '"tag":"[^"]*"'
Parse both the edition and the major version from the tag:
| Tag format | Edition | Example |
| ---------- | --------------- | --------------------------- |
| v0.X.Y | OSS (Community) | v0.60.1 → major 60, OSS |
| v1.X.Y | Enterprise (EE) | v1.60.1 → major 60, EE |
If major version < 49, tell the user the Embedding SDK requires Metabase 49+ and stop.
If the tag starts with v1., the instance is Enterprise Edition — use full JWT SSO embedding. Do not fall back to guest embedding or any OSS-only auth path.
Remember the major version number — you will need it in Step 3.
Automatically enable the SDK so the user doesn't have to toggle it manually in the admin panel:
source .env.metabase && \
curl -s -X PUT "$METABASE_INSTANCE_URL/api/setting/enable-embedding-sdk" \
-H "X-API-Key: $METABASE_ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{"value": true}'
If this returns an error (e.g., 403), tell the user to enable it manually at <INSTANCE_URL>/admin/settings/embedding and move on.
Do NOT fetch llms.txt yet. You need dashboard IDs first.
Run both of these:
source .env.metabase && \
curl -s "$METABASE_INSTANCE_URL/api/search?models=dashboard&archived=false" \
-H "X-API-Key: $METABASE_ADMIN_API_KEY"
source .env.metabase && \
curl -s "$METABASE_INSTANCE_URL/api/automagic-dashboards/database/1/candidates" \
-H "X-API-Key: $METABASE_ADMIN_API_KEY"
Filter and prioritize the results:
Format like this:
Existing dashboards:
- Sales Overview (ID 3)
- Customer Analysis (ID 7) ...
Or I can create a new dashboard from your data: A. Orders table B. Products table ...
Which ones should I embed? (e.g. "1 and 3" or "A")
Wait for the user to pick. If they choose a table, generate and save the X-ray dashboard:
source .env.metabase && \
DASHBOARD=$(curl -s "$METABASE_INSTANCE_URL/api/automagic-dashboards/table/<TABLE_ID>" \
-H "X-API-Key: $METABASE_ADMIN_API_KEY")
source .env.metabase && \
curl -s "$METABASE_INSTANCE_URL/api/dashboard/save" \
-H "X-API-Key: $METABASE_ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d "$DASHBOARD"
The save response contains the persisted dashboard with a real id field. Use these IDs going forward.
You MUST have real dashboard IDs before reaching this step. If you don't, go back to Step 2.
Now fetch the versioned docs index using the major version from Step 2a:
curl -s https://www.metabase.com/docs/v0.<MAJOR>/llms.txt
Fall back to https://www.metabase.com/docs/latest/llms.txt if empty. This contains correct prop names, auth config shapes, SDK install commands, and breaking changes for this version. Do not fetch llms-embedding-full.txt (too large).
Follow the auth setup instructions in llms.txt. In particular:
METABASE_JWT_SECRET in their server-side environment only (never a browser-accessible env var)llms.txtCheck whether @metabase/embedding-sdk-react is already in the user's package.json.
llms.txt (the correct dist-tag matches the instance major version).Use llms.txt as the authoritative reference for all API shapes. Write files directly into the user's project — edit existing files in place rather than creating new ones alongside them.
MetabaseProvider receives its URL. Never generate apiKey, METABASE_API_KEY, api-key, or x-api-key — not even as a placeholder. Deviate only if the user explicitly asks and acknowledges the security risk.VITE_METABASE_URL (Vite), NEXT_PUBLIC_METABASE_URL (Next.js), etc. Never hardcode.<InteractiveDashboard dashboardId={7} />. Dashboard IDs are not secrets. Never use import.meta.env.VITE_METABASE_DASHBOARD_*, env vars, config objects, parseDashboardId helpers, or any indirection for dashboard IDs. The goal is clean, minimal code the user can instantly understand and tweak.After generating the embedding code, inspect the user's app for existing styles — look at CSS variables, Tailwind config, or theme files. Set the theme prop on MetabaseProvider to match the app's look and feel. At minimum, align:
colors.brand — the app's primary/accent colorcolors.background — to match the page background so the embed doesn't look like a white box on a dark page (or vice versa)fontFamily — to match the app's fontRefer to llms.txt for the full theme shape. Keep it minimal — only set values that differ from Metabase defaults.
tools
Drive a Metabase instance from the terminal via the `mb` CLI. Authenticate with named profiles; inspect databases (list, get, full metadata rollup, schemas, tables in a schema) and trigger manual schema sync / field-values rescan; inspect tables, fields; list/get/create/update/archive cards (questions, models, metrics) and run them as JSON/CSV/XLSX; list/get/create/update dashboards and patch dashcards; list/get/create collections and traverse the hierarchy by id, entity_id, or "root"/"trash" (with items and recursive tree); list/get/create/update/archive native query snippets, segments, and measures; author/update/run transforms and schedule transform-jobs; read/update settings; search content (cards, dashboards, collections, transforms, metrics); manage Enterprise workspaces; git-sync to/from a git remote (status, dirty, import, export, branches, stash, add/remove a collection from sync). Use whenever the user wants to interact with a Metabase from the terminal — "log into metabase", "what profiles do I have", "list cards", "run card 42 as CSV", "create a transform", "list dashboards", "move a dashcard", "list collections", "what's in collection 4", "show the collection tree", "list snippets", "create a segment", "archive a measure", "search metabase for X", "spin up a workspace", "import the latest changes", "add a directory to git sync", "set a setting", "what schemas are in this database", "trigger a sync", "rescan field values", or anything hitting `mb <verb>`.
development
Runs the Metabase semantic checker against a tree of Representation Format YAML files to verify that all references resolve — cross-entity references (collection_id, dashboard_id, parent_id, parameter source cards, snippet references, transform tags, etc.) and references to columns inside MBQL and native queries. Slow (≥1 min per run). Only use when the user explicitly asks to verify entity references or column references in MBQL/SQL queries; in most cases this runs as a CI step, not locally. Requires database metadata on disk (by default `.metadata/table_metadata.json`).
development
Understands the Metabase Database Metadata Format — a YAML-based on-disk representation of databases, tables, and fields synced from a Metabase instance. Use when the user needs to read, edit, or understand metadata files produced by `@metabase/database-metadata`, or when reasoning about a project's schema (columns, types, FK relationships) through the `.metadata/databases` folder.
development
Understands the Metabase Representation Format — a YAML-based serialization format for Metabase content (collections, cards, dashboards, documents, segments, measures, snippets, transforms). Use when the user needs to create, edit, understand, or validate Metabase representation YAML files, or when working with Metabase serialization/deserialization (serdes). Covers entity schemas, MBQL and native queries, visualization settings, parameters, and folder structure.