--- name: metabase-react-sdk-setup description: First-time setup for the Metabase React SDK — instance detection, API key, dashboard discovery, JWT auth, SDK installation, and initial embedding code. --- 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. ## Step 1 — Get the Metabase URL and 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: ```bash 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.metabase` in the project root. Please fill in both values: > > 1. Set `METABASE_INSTANCE_URL` to your Metabase URL (e.g. `http://localhost:3000`) > 2. Open `{your URL}/admin/settings/authentication/api-keys`, create a new API key > 3. Set `METABASE_ADMIN_API_KEY` to that key > 4. 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. ## Step 2 — Detect version and discover dashboards Now that you have an API key, detect the version and find dashboards. ### 2a — Detect version ```bash 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. ### 2b — Enable the Embedding SDK Automatically enable the SDK so the user doesn't have to toggle it manually in the admin panel: ```bash 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 **/admin/settings/embedding** and move on. **Do NOT fetch `llms.txt` yet.** You need dashboard IDs first. ### 2c — Find dashboards and table candidates Run both of these: ```bash source .env.metabase && \ curl -s "$METABASE_INSTANCE_URL/api/search?models=dashboard&archived=false" \ -H "X-API-Key: $METABASE_ADMIN_API_KEY" ``` ```bash 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: - **Exclude** any dashboards from the "Usage analytics" collection — those are internal Metabase admin dashboards, not user content. - **Deprioritize** anything from the "Sample Database" — prefer the user's own databases and dashboards. - Pick the **top 5** most relevant to what the user asked for from each category. Do not dump every result. Format like this: > **Existing dashboards:** > > 1. Sales Overview (ID 3) > 2. 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: ```bash source .env.metabase && \ DASHBOARD=$(curl -s "$METABASE_INSTANCE_URL/api/automagic-dashboards/table/" \ -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. ## Step 3 — Fetch docs, set up auth, and install SDK 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: ```bash curl -s https://www.metabase.com/docs/v0./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). ### 3a — Set up JWT SSO authentication (skip if already done) Follow the auth setup instructions in `llms.txt`. In particular: - Retrieve the JWT signing secret from Metabase: **Settings → Admin → Embedding → Embedding secret key** - Tell the user to save it as `METABASE_JWT_SECRET` in their server-side environment only (never a browser-accessible env var) - Ask which backend framework they are using (Next.js API route, Express, Fastify, etc.) and scaffold a minimal JWT signing endpoint following the pattern in `llms.txt` ### 3b — Install the SDK (skip if already installed at correct version) Check whether `@metabase/embedding-sdk-react` is already in the user's `package.json`. - If not installed: use the install command from `llms.txt` (the correct dist-tag matches the instance major version). - If already installed: verify the major version matches. Warn on mismatch and offer to update. ## Step 4 — Generate embedding code 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. ### Code conventions (override anything in the docs) - **JWT SSO only**: API keys grant admin-level access and are not safe for end-user embeds. Use a server-side JWT signing endpoint; `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. - **Instance URL from env**: `VITE_METABASE_URL` (Vite), `NEXT_PUBLIC_METABASE_URL` (Next.js), etc. Never hardcode. - **Dashboard IDs as inline literals**: always hardcode dashboard IDs directly in JSX — e.g. ``. 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. - **Secrets server-side only**: JWT secrets must never appear in browser-accessible env vars or frontend code. ### Theming 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 color - `colors.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 font Refer to `llms.txt` for the full theme shape. Keep it minimal — only set values that differ from Metabase defaults.