Skip to main content

Metabase Local Testing Guide

This guide will help you test the Metabase integration locally before deploying to staging/production.

Prerequisites

  • Docker and Docker Compose installed
  • Backend running locally (port 4000)
  • Frontend PWA or Web App running locally
  • A valid Firebase authentication token for API requests

Step 1: Start Metabase Locally

Metabase is already configured in docker-compose.yml. Start it:

# Start Metabase (and dependencies)
docker compose up metabase -d

# Check if Metabase is running
docker compose ps metabase

# View Metabase logs
docker compose logs -f metabase

Metabase will be available at: http://localhost:3002

Note: The first startup may take 1-2 minutes. Wait until you see "Metabase initialization complete" in the logs.

Step 2: Configure Metabase

2.1 Initial Setup

  1. Open http://localhost:3002 in your browser
  2. Complete the initial setup wizard:
    • Create an admin account (remember these credentials!)
    • Configure your organization details
    • Skip database connection for now (we'll add it later)

2.2 Enable Static Embedding (FREE)

Important: We're using Metabase Open Source (self-hosted), which includes Static Embedding for FREE. You may see a "Embedded Analytics" tab that shows pricing - ignore that, we only need the free "Static Embedding" feature.

Step-by-step:

  1. Navigate to SettingsAdminEmbedding

    • You'll see two tabs: "Static embedding" and "Embedded Analytics"
  2. Click on the "Static embedding" tab

    • ⚠️ Don't click "Embedded Analytics" - that's the paid feature ($575/month)
    • If you accidentally click it and see a pricing page, just go back to "Static embedding"
  3. Toggle the switch "Enable static embedding" to ON

    • The switch should turn blue/green when enabled
  4. A Secret key will appear (long alphanumeric string)

    • Example format: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6
    • Copy this key immediately - you'll need it for your backend configuration
    • Store it securely - you'll add it to your .env file in the next step
  5. Verify the key is copied

    • The secret key is used to sign JWT tokens for embedding
    • It must match exactly between Metabase and your backend

What you should see:

  • ✅ "Static embedding" tab is active
  • ✅ "Enable static embedding" toggle is ON
  • ✅ A long secret key is displayed
  • ❌ No pricing information or payment prompts

Troubleshooting:

  • If you don't see a "Static embedding" tab, make sure you're using Metabase Open Source (not Cloud)
  • If the toggle won't enable, refresh the page and try again
  • If you see a pricing page, you clicked the wrong tab - go back to "Static embedding"

2.3 Connect to Your Local Database (Optional)

If you want to test with real data:

  1. Go to SettingsAdminDatabasesAdd Database
  2. Select PostgreSQL
  3. Configure connection:
    • Name: FlowPOS Local DB
    • Host: postgres_dev (Docker service name) or localhost
    • Port: 5432 (or 5435 if connecting from host)
    • Database name: flowpos_dev
    • Username: flowpos
    • Password: flowpos
    • Additional JDBC connection string options: ?sslmode=disable
  4. Click Save

Step 3: Configure Backend Environment Variables

Add these environment variables to your .env file (or export them):

# Metabase Configuration
METABASE_SITE_URL=http://localhost:3002
METABASE_EMBED_SECRET_KEY=<your-embedding-secret-key-from-step-2.2>

Important: The METABASE_EMBED_SECRET_KEY must match the secret key from Metabase's embedding settings.

Example .env addition

# Metabase Local Testing
METABASE_SITE_URL=http://localhost:3002
METABASE_EMBED_SECRET_KEY=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6

Step 4: Restart Backend

Restart your backend to load the new environment variables:

# If using Docker
docker compose restart backend

# If running directly
cd apps/backend
pnpm start:dev

Step 5: Create a Test Dashboard in Metabase

5.1 Create a Test SQL Question

Option A: Using Native Query (Recommended for Testing)

  1. In Metabase, click the "+" button in the top navigation (or go to Browse Data)
  2. Select "Native query" (or "SQL query")
    • If you don't see this option, try: "New""Question""Native query"
  3. In the SQL editor, paste this simple test query:
SELECT
CAST({{business_id}} AS TEXT) AS business_id,
CURRENT_DATE AS test_date,
'Test Dashboard' AS message

Important:

  • {{business_id}} is NOT inside quotes - parameters cannot be used inside string literals
  • We use CAST({{business_id}} AS TEXT) to ensure it's treated as text (since it's a UUID)
  • If you get an error "parameters cannot be used in comments or as identifiers", check that the parameter is not inside quotes
  1. Add a variable:

    • Look for a "Variables" button or section (usually below the SQL editor)
    • Click "Add a variable" or the "+" button
    • Variable name: business_id
    • Variable type: Text
    • Click "Add" or "Done"
  2. Click "Run" to test the query (it will prompt for business_id - enter any test UUID like 550e8400-e29b-41d4-a716-446655440000)

Note: If you get an error about "parameters cannot be used in comments or as identifiers", make sure:

  • The parameter {{business_id}} is NOT inside quotes
  • The parameter is used as a value, not as a column name or identifier
  1. Click "Save""Save as question"
    • Name it: Test Business Query
    • Choose a collection (or create a new one)
    • Click "Save"

Alternative: If you can't find Native Query

If the navigation is different in your Metabase version:

  1. Click "New" or "+" button
  2. Select "Question"
  3. Choose "Native query" or "SQL"
  4. Follow steps 3-6 above

Note: The exact navigation may vary slightly depending on your Metabase version, but look for options like "New", "Question", "Native query", or "SQL query".

5.2 Create a Dashboard

  1. Go to DashboardsNew Dashboard
  2. Name it: Test Dashboard
  3. Click Add a question → Select your test question
  4. Save the dashboard
  5. Note the Dashboard ID from the URL (e.g., http://localhost:3002/dashboard/1 → ID is 1)

5.3 Configure Embedding

  1. In your dashboard, click (three dots) → Embed this dashboard
  2. Enable embedding for this dashboard
  3. Configure parameters:
    • Find business_id parameter
    • Mark it as Locked (users can't change it)
    • Mark it as Hidden (users can't see it)
  4. Click Save
  5. Copy the Dashboard ID (you'll need it for testing)

Step 6: Test Backend Endpoint

6.1 Get a Firebase Auth Token

You'll need a valid Firebase ID token. You can get this from:

  • Your frontend app (check browser DevTools → Application → Cookies)
  • Or use your existing authentication flow

6.2 Test with cURL

# Replace <YOUR_TOKEN> with your Firebase ID token
# Replace <DASHBOARD_ID> with your dashboard ID (e.g., 1)
# Replace <BUSINESS_ID> with a test business ID (UUID format)

curl -X GET "http://localhost:4000/reports/dashboard/1/embed-url?businessId=550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer <YOUR_TOKEN>" \
-H "Content-Type: application/json"

Expected Response:

{
"embedUrl": "http://localhost:3002/embed/dashboard/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...?bordered=true&titled=true"
}

6.3 Test Error Cases

# Missing businessId (should fail)
curl -X GET "http://localhost:4000/reports/dashboard/1/embed-url" \
-H "Authorization: Bearer <YOUR_TOKEN>"

# Invalid dashboardId (should fail)
curl -X GET "http://localhost:4000/reports/dashboard/invalid/embed-url?businessId=550e8400-e29b-41d4-a716-446655440000" \
-H "Authorization: Bearer <YOUR_TOKEN>"

Step 7: Test Frontend Components

7.1 Test PWA Component

  1. Start your PWA frontend:

    cd apps/frontend-pwa
    pnpm dev
  2. Create a test page or add to an existing page:

import { MetabaseDashboardFrame } from "@/features/reports/MetabaseDashboardFrame";

export function TestReportsPage() {
// Replace 1 with your actual dashboard ID
return (
<div className="p-4">
<h1>Test Metabase Dashboard</h1>
<MetabaseDashboardFrame
dashboardId={1}
height="600px"
/>
</div>
);
}
  1. Navigate to the page and verify:
    • Loading state appears initially
    • Dashboard loads in iframe
    • No console errors

7.2 Test Web App Component

  1. Start your Web App:

    cd apps/web-app
    pnpm dev
  2. Create a test page (e.g., app/(private)/business/[businessId]/reports/page.tsx):

"use client";

import { MetabaseDashboardFrame } from "@/features/reports/MetabaseDashboardFrame";

export default function ReportsPage() {
// Replace 1 with your actual dashboard ID
return (
<div className="p-4">
<h1>Test Metabase Dashboard</h1>
<MetabaseDashboardFrame
dashboardId={1}
height="600px"
/>
</div>
);
}
  1. Navigate to the page and verify the dashboard loads

Step 8: Verify JWT Token

You can decode the JWT token from the embed URL to verify it contains the correct business_id:

  1. Copy the embed URL from the backend response

  2. Extract the JWT token (the part after /embed/dashboard/)

  3. Decode it at https://jwt.io

  4. Verify the payload contains:

    {
    "resource": { "dashboard": 1 },
    "params": {
    "business_id": "550e8400-e29b-41d4-a716-446655440000"
    },
    "exp": 1234567890
    }

Troubleshooting

Backend Errors

Error: "METABASE_SITE_URL is not configured"

  • Solution: Add METABASE_SITE_URL to your .env file

Error: "METABASE_EMBED_SECRET_KEY is not configured"

  • Solution: Add METABASE_EMBED_SECRET_KEY to your .env file (must match Metabase embedding secret)

Error: "businessId is required"

  • Solution: Make sure you're passing businessId as a query parameter

Frontend Errors

Error: "Failed to load dashboard"

  • Check browser console for detailed error
  • Verify backend is running and accessible
  • Verify Firebase token is valid
  • Check network tab for API request/response

Dashboard shows "Invalid token"

  • Verify METABASE_EMBED_SECRET_KEY matches Metabase embedding secret
  • Check that embedding is enabled in Metabase
  • Verify dashboard ID is correct

Dashboard loads but shows no data

  • Verify business_id parameter is configured in Metabase question
  • Check that the question includes WHERE business_id = {{business_id}}
  • Verify the business_id value exists in your database

Metabase Issues

Metabase won't start

  • Check Docker logs: docker compose logs metabase
  • Verify port 3002 is not in use
  • Try restarting: docker compose restart metabase

Can't access Metabase UI

  • Verify Metabase is running: docker compose ps metabase
  • Check if port 3002 is accessible: curl http://localhost:3002/api/health
  • Try accessing via http://127.0.0.1:3002 instead of localhost

Next Steps

Once local testing is successful:

  1. ✅ Backend endpoint returns valid embed URLs
  2. ✅ Frontend components load dashboards correctly
  3. ✅ JWT tokens contain correct business_id
  4. ✅ Data isolation works (different business_id values show different data)

You're ready to proceed with:

  • Phase 3: Secrets & Configuration (add secrets to Doppler)
  • Phase 4: Deployment (deploy to staging/production)

Additional Resources