React SDK for embedding Lightdash analytics components into applications
npx @tessl/cli install tessl/npm-lightdash--sdk@0.2231.0React component library for embedding interactive Lightdash analytics (dashboards, charts, explore) into React applications with JWT authentication.
Package: @lightdash/sdk (npm)
TypeScript/React | Peer deps: react@^18.x || ^19.x, react-dom@^18.x || ^19.x
Install: npm install @lightdash/sdk
import { Dashboard, Chart, Explore } from '@lightdash/sdk';
import '@lightdash/sdk/sdk.css';
function App() {
const token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'; // JWT with projectUuid in payload
return (
<Dashboard
instanceUrl="https://your-instance.lightdash.cloud"
token={token}
styles={{ backgroundColor: '#f5f5f5', fontFamily: 'Arial, sans-serif' }}
/>
);
}Embeds a complete Lightdash dashboard with interactivity, filtering, and exploration.
function Dashboard(props: DashboardProps): JSX.Element | null;
interface DashboardProps {
instanceUrl: string; // Lightdash instance URL (e.g., 'https://your-instance.lightdash.cloud')
token: Promise<string> | string; // JWT token with projectUuid in payload.content.projectUuid
styles?: {
backgroundColor?: string; // Container background color
fontFamily?: string; // Applied to text, tables, and charts
};
filters?: SdkFilter[]; // Optional filters to apply
contentOverrides?: LanguageMap; // i18n text overrides (from @lightdash/common)
onExplore?: (options: { chart: SavedChart }) => void; // Callback when navigating to explore
}Example with async token and filters:
import { Dashboard } from '@lightdash/sdk';
import '@lightdash/sdk/sdk.css';
import { FilterOperator } from '@lightdash/common';
async function getToken(): Promise<string> {
const response = await fetch('/api/lightdash-token');
if (!response.ok) throw new Error('Failed to fetch token');
const data = await response.json();
return data.token;
}
function DashboardEmbed() {
const handleExplore = ({ chart }: { chart: SavedChart }) => {
console.log('Exploring chart:', chart.name);
// Navigate to explore view or open modal
};
return (
<Dashboard
instanceUrl="https://your-instance.lightdash.cloud"
token={getToken()}
filters={[
{
model: 'payments',
field: 'payment_method',
operator: 'equals' as const,
value: 'credit_card'
}
]}
styles={{ backgroundColor: '#ffffff', fontFamily: 'Inter, sans-serif' }}
onExplore={handleExplore}
/>
);
}Embeds a single Lightdash chart by UUID.
function Chart(props: ChartProps): JSX.Element | null;
interface ChartProps {
id: string; // Chart UUID
instanceUrl: string;
token: Promise<string> | string;
styles?: {
backgroundColor?: string;
fontFamily?: string;
};
contentOverrides?: LanguageMap; // from @lightdash/common
}Example:
import { Chart } from '@lightdash/sdk';
import '@lightdash/sdk/sdk.css';
function ChartEmbed() {
return (
<Chart
id="550e8400-e29b-41d4-a716-446655440000"
instanceUrl="https://your-instance.lightdash.cloud"
token={token}
styles={{ backgroundColor: '#f8f9fa' }}
/>
);
}Embeds the Lightdash explore interface for interactive data exploration.
function Explore(props: ExploreProps): JSX.Element | null;
interface ExploreProps {
exploreId: string; // ID of the explore to load
savedChart: SavedChart; // Chart configuration to initialize with (from @lightdash/common)
instanceUrl: string;
token: Promise<string> | string;
styles?: {
backgroundColor?: string;
fontFamily?: string;
};
filters?: SdkFilter[];
contentOverrides?: LanguageMap; // from @lightdash/common
onExplore?: (options: { chart: SavedChart }) => void;
}Example:
import { Explore } from '@lightdash/sdk';
import '@lightdash/sdk/sdk.css';
import { SavedChart } from '@lightdash/common';
function ExploreEmbed() {
const savedChart: SavedChart = {
uuid: '123e4567-e89b-12d3-a456-426614174000',
projectUuid: 'proj-123',
name: 'Revenue Analysis',
tableName: 'orders',
metricQuery: {
exploreName: 'orders',
dimensions: ['orders.created_date'],
metrics: ['orders.total_revenue'],
filters: {},
sorts: [],
limit: 500,
tableCalculations: []
},
chartConfig: { type: 'cartesian', config: {} },
tableConfig: { columnOrder: [] },
updatedAt: new Date(),
organizationUuid: 'org-123',
spaceUuid: 'space-123',
spaceName: 'Analytics',
pinnedListUuid: null,
pinnedListOrder: null,
dashboardUuid: null,
dashboardName: null,
colorPalette: [],
isPrivate: false,
access: [],
slug: 'revenue-analysis'
};
return (
<Explore
exploreId="orders"
savedChart={savedChart}
instanceUrl="https://your-instance.lightdash.cloud"
token={token}
filters={[
{
model: 'orders',
field: 'status',
operator: 'equals' as const,
value: 'completed'
}
]}
/>
);
}const Lightdash: {
Dashboard: typeof Dashboard;
Chart: typeof Chart;
Explore: typeof Explore;
};
export default Lightdash;Usage:
import Lightdash from '@lightdash/sdk';
import '@lightdash/sdk/sdk.css';
<Lightdash.Dashboard instanceUrl={url} token={token} />Note: Not exported from @lightdash/sdk or @lightdash/common - define in your application.
interface SdkFilter {
model: string; // Table/model name
field: string; // Field name within model
operator: `${FilterOperator}`; // Filter operator (from @lightdash/common)
value: unknown | unknown[]; // Filter value(s)
}Import from @lightdash/common:
import { FilterOperator } from '@lightdash/common';type FilterOperator =
| 'isNull' | 'notNull'
| 'equals' | 'notEquals'
| 'startsWith' | 'endsWith'
| 'include' | 'doesNotInclude'
| 'lessThan' | 'lessThanOrEqual'
| 'greaterThan' | 'greaterThanOrEqual'
| 'inThePast' | 'notInThePast'
| 'inTheNext'
| 'inTheCurrent' | 'notInTheCurrent'
| 'inBetween' | 'notInBetween';Import from @lightdash/common:
import { SavedChart } from '@lightdash/common';interface SavedChart {
uuid: string;
projectUuid: string;
name: string;
description?: string;
tableName: string;
metricQuery: MetricQuery;
pivotConfig?: { columns: string[] };
chartConfig: ChartConfig;
tableConfig: { columnOrder: string[] };
parameters?: ParametersValuesMap;
updatedAt: Date;
updatedByUser?: UpdatedByUser;
organizationUuid: string;
spaceUuid: string;
spaceName: string;
pinnedListUuid: string | null;
pinnedListOrder: number | null;
dashboardUuid: string | null;
dashboardName: string | null;
colorPalette: string[];
isPrivate: boolean;
access: SpaceShare[];
slug: string;
}
interface UpdatedByUser {
userUuid: string;
firstName: string;
lastName: string;
}
interface SpaceShare {
userUuid: string;
firstName: string;
lastName: string;
role: string;
}
interface MetricQuery {
exploreName: string;
dimensions: string[];
metrics: string[];
filters: Record<string, unknown>; // Filter configuration object
sorts: SortField[];
limit: number;
tableCalculations: TableCalculation[];
additionalMetrics?: AdditionalMetric[];
customDimensions?: CustomDimension[];
metricOverrides?: Record<string, unknown>;
timezone?: string;
metadata?: {
hasADateDimension: {
label: string;
name: string;
table: string;
};
};
periodOverPeriod?: PeriodOverPeriodConfig;
}
interface SortField {
fieldId: string;
descending: boolean;
nullsFirst?: boolean;
}
interface ChartConfig {
type: 'cartesian' | 'pie' | 'table' | 'big_number' | string;
config: Record<string, unknown>; // Chart-specific configuration
}
type ParametersValuesMap = Record<string, unknown>;
type TableCalculation = Record<string, unknown>; // Table calculation configuration
type AdditionalMetric = Record<string, unknown>; // Additional metric configuration
type CustomDimension = Record<string, unknown>; // Custom dimension configuration
type PeriodOverPeriodConfig = Record<string, unknown>; // Period-over-period comparison configImport from @lightdash/common:
import { LanguageMap } from '@lightdash/common';type LanguageMap = Partial<ChartAsCodeLanguageMap & DashboardAsCodeLanguageMap>;
// Used to override text and labels in embedded components
// Specific keys depend on the embedded component typeToken payload structure:
{
"content": {
"projectUuid": "string" // Required: UUID of the Lightdash project
}
}Token Format:
header.payload.signatureprojectUuid from tokenError Handling:
"Invalid JWT token""Error decoding token""Error retrieving token"Async Token Support:
Components accept Promise<string> for async token retrieval. Component won't render until Promise resolves:
async function getToken(): Promise<string> {
const response = await fetch('/api/lightdash-token');
if (!response.ok) throw new Error('Failed to fetch token');
return (await response.json()).token;
}
<Dashboard instanceUrl={url} token={getToken()} />All components accept styles prop:
styles?: {
backgroundColor?: string; // CSS color value
fontFamily?: string; // CSS font-family value
}The fontFamily is applied to:
Example:
<Dashboard
instanceUrl={url}
token={token}
styles={{
backgroundColor: '#1a1a1a',
fontFamily: "'Roboto', 'Helvetica', 'Arial', sans-serif"
}}
/>Dashboard and Explore support filtering via filters prop:
import { Dashboard } from '@lightdash/sdk';
import { FilterOperator } from '@lightdash/common';
const filters: SdkFilter[] = [
{
model: 'users',
field: 'country',
operator: 'equals' as const,
value: 'United States'
},
{
model: 'orders',
field: 'total',
operator: 'greaterThan' as const,
value: 100
},
{
model: 'products',
field: 'category',
operator: 'include' as const,
value: ['Electronics', 'Computers']
}
];
<Dashboard instanceUrl={url} token={token} filters={filters} />Filter Operators:
equals, notEquals, lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqualstartsWith, endsWith, include, doesNotIncludeisNull, notNullinThePast, notInThePast, inTheNext, inTheCurrent, notInTheCurrentinBetween, notInBetweenCustomize text and labels for i18n:
import { LanguageMap } from '@lightdash/common';
<Dashboard
instanceUrl={url}
token={token}
contentOverrides={{
// Override specific text strings
// Keys depend on component type
} as LanguageMap}
/>Dashboard and Explore support onExplore callback:
import { Dashboard } from '@lightdash/sdk';
import { SavedChart } from '@lightdash/common';
import { useState } from 'react';
function DashboardWithExplore() {
const [exploreChart, setExploreChart] = useState<SavedChart | null>(null);
return (
<>
<Dashboard
instanceUrl={url}
token={token}
onExplore={({ chart }: { chart: SavedChart }) => {
setExploreChart(chart);
// Navigate to custom explore view or open modal
}}
/>
{exploreChart && <div>Exploring: {exploreChart.name}</div>}
</>
);
}Note: Chart component does not support onExplore.
Required for proper styling:
import '@lightdash/sdk/sdk.css';Includes Mantine UI styles, Lightdash component styles, and layout styles. Import once in your application entry point or in the component using the SDK.
The instanceUrl prop specifies the Lightdash instance:
// Cloud instance
instanceUrl: "https://your-instance.lightdash.cloud"
// Self-hosted instance
instanceUrl: "https://lightdash.your-company.com"Notes:
projectUuid extraction