Creating, updating, and managing dashboards with tiles, filters, and tabs.
Dashboards combine multiple visualizations and content into organized layouts with:
type Dashboard = {
organizationUuid: string;
projectUuid: string;
uuid: string;
name: string;
description?: string;
updatedAt: Date;
tiles: DashboardTile[];
filters: DashboardFilters;
parameters?: DashboardParameters;
tabs?: DashboardTab[];
spaceUuid: string;
spaceName: string;
views: number;
firstViewedAt: Date | null;
pinnedListUuid: string | null;
pinnedListOrder: number | null;
slug: string;
dashboardVersionId: number;
updatedByUser?: UpdatedByUser;
isPrivate: boolean | null;
access: SpaceShare[] | null;
config?: DashboardConfig;
};
type DashboardDAO = Omit<Dashboard, 'isPrivate' | 'access'>;type DashboardConfig = {
isDateZoomDisabled: boolean;
pinnedParameters?: string[];
};AI-generated dashboard summaries with customizable tone and audience:
enum DashboardSummaryTone {
FRIENDLY = 'friendly',
FORMAL = 'formal',
DIRECT = 'direct',
ENTHUSIASTIC = 'enthusiastic',
}
type DashboardSummary = {
dashboardSummaryUuid: string;
dashboardUuid: string;
dashboardVersionId: number;
context?: string | null;
tone: DashboardSummaryTone;
audiences: string[];
summary: string;
createdAt: Date;
};Utility types for working with partial dashboard representations:
type DashboardBasicDetails = Pick<
Dashboard,
| 'uuid'
| 'name'
| 'description'
| 'updatedAt'
| 'projectUuid'
| 'updatedByUser'
| 'organizationUuid'
| 'spaceUuid'
| 'views'
| 'firstViewedAt'
| 'pinnedListUuid'
| 'pinnedListOrder'
> & { validationErrors?: ValidationSummary[] };
type DashboardBasicDetailsWithTileTypes = DashboardBasicDetails & {
tileTypes: DashboardTileTypes[];
};
type SpaceDashboard = DashboardBasicDetails;type DashboardTab = {
uuid: string;
name: string;
order: number;
};
type DashboardTabWithUrls = DashboardTab & {
nextUrl: string | null;
prevUrl: string | null;
selfUrl: string;
};Tabs organize tiles into separate views within a dashboard.
enum DashboardTileTypes {
SAVED_CHART = 'saved_chart',
MARKDOWN = 'markdown',
LOOM = 'loom',
SQL_CHART = 'sql_chart',
}interface DashboardBaseTile {
uuid: string;
type: DashboardTileTypes;
x: number; // Grid position X
y: number; // Grid position Y
h: number; // Height in grid units
w: number; // Width in grid units
tabUuid?: string; // Optional tab UUID
}interface DashboardChartTile extends DashboardBaseTile {
type: DashboardTileTypes.SAVED_CHART;
properties: {
savedChartUuid: string | null;
chartName?: string;
title?: string;
hideTitle?: boolean;
belongsToDashboard?: boolean;
lastVersionChartKind?: ChartKind | null;
chartSlug?: string;
};
}Example:
const chartTile: DashboardChartTile = {
uuid: 'tile-1',
type: DashboardTileTypes.SAVED_CHART,
x: 0,
y: 0,
h: 4,
w: 6,
properties: {
savedChartUuid: 'chart-uuid',
title: 'Revenue by Month',
hideTitle: false,
},
};interface DashboardMarkdownTile extends DashboardBaseTile {
type: DashboardTileTypes.MARKDOWN;
properties: {
title: string;
content: string;
};
}Example:
const markdownTile: DashboardMarkdownTile = {
uuid: 'tile-2',
type: DashboardTileTypes.MARKDOWN,
x: 6,
y: 0,
h: 2,
w: 6,
properties: {
title: 'Overview',
content: '# Dashboard Overview\n\nThis dashboard shows key metrics.',
},
};interface DashboardLoomTile extends DashboardBaseTile {
type: DashboardTileTypes.LOOM;
properties: {
title: string;
url: string;
hideTitle?: boolean;
};
}Example:
const loomTile: DashboardLoomTile = {
uuid: 'tile-3',
type: DashboardTileTypes.LOOM,
x: 0,
y: 4,
h: 4,
w: 6,
properties: {
title: 'Dashboard Walkthrough',
url: 'https://www.loom.com/share/...',
},
};interface DashboardSqlChartTile extends DashboardBaseTile {
type: DashboardTileTypes.SQL_CHART;
properties: {
savedSqlUuid: string | null;
chartName?: string;
title?: string;
hideTitle?: boolean;
lastVersionChartKind?: ChartKind | null;
chartSlug?: string;
};
}type DashboardTile =
| DashboardChartTile
| DashboardMarkdownTile
| DashboardLoomTile
| DashboardSqlChartTile;When creating tiles for dashboards, use these types:
type CreateDashboardTileBase = {
uuid?: string;
type: DashboardTileTypes;
x: number;
y: number;
h: number;
w: number;
tabUuid?: string;
};
type CreateDashboardChartTile = CreateDashboardTileBase & {
type: DashboardTileTypes.SAVED_CHART;
properties: {
title?: string;
hideTitle?: boolean;
savedChartUuid: string | null;
belongsToDashboard?: boolean;
chartName?: string | null;
lastVersionChartKind?: ChartKind | null;
chartSlug?: string;
};
};
type CreateDashboardMarkdownTile = CreateDashboardTileBase & {
type: DashboardTileTypes.MARKDOWN;
properties: {
title: string;
content: string;
};
};
type CreateDashboardLoomTile = CreateDashboardTileBase & {
type: DashboardTileTypes.LOOM;
properties: {
title: string;
hideTitle?: boolean;
url: string;
};
};
type CreateDashboardSqlChartTile = CreateDashboardTileBase & {
type: DashboardTileTypes.SQL_CHART;
properties: {
title?: string;
savedSqlUuid: string | null;
chartName: string;
hideTitle?: boolean;
chartSlug?: string;
};
};interface DashboardFilters {
dimensions: DashboardFilterRule[];
metrics: DashboardFilterRule[];
tableCalculations: DashboardFilterRule[];
}
interface DashboardAvailableFilters {
savedQueryFilters: Record<string, number[]>;
allFilterableFields: FilterableDimension[];
}Dashboard filters can be applied across multiple tiles, with per-tile field targeting.
type CreateDashboard = {
name: string;
description?: string;
tiles: Array<
| CreateDashboardChartTile
| CreateDashboardMarkdownTile
| CreateDashboardLoomTile
| CreateDashboardSqlChartTile
>;
filters?: DashboardFilters;
parameters?: DashboardParameters;
pinnedParameters?: string[];
updatedByUser?: Pick<UpdatedByUser, 'userUuid'>;
tabs: DashboardTab[];
config?: DashboardConfig;
spaceUuid?: string;
}Example:
import { type CreateDashboard } from '@lightdash/common';
const newDashboard: CreateDashboard = {
name: 'Sales Dashboard',
description: 'Monthly sales metrics and trends',
spaceUuid: 'space-uuid',
filters: {
dimensions: [],
metrics: [],
tableCalculations: [],
},
};Convenience type for creating a dashboard with charts in one operation:
type CreateDashboardWithCharts = {
name: string;
description?: string;
spaceUuid: string;
charts: CreateSavedChart[];
};interface UpdateDashboard {
name?: string;
description?: string;
tiles?: DashboardTile[];
filters?: DashboardFilters;
tabs?: DashboardTab[];
}function isDashboardChartTileType(
tile: DashboardTile
): tile is DashboardChartTile;
function isDashboardMarkdownTileType(
tile: DashboardTile
): tile is DashboardMarkdownTile;
function isDashboardLoomTileType(
tile: DashboardTile
): tile is DashboardLoomTile;
function isDashboardSqlChartTile(
tile: DashboardTile
): tile is DashboardSqlChartTile;Example:
import {
isDashboardChartTileType,
isDashboardMarkdownTileType,
} from '@lightdash/common';
tiles.forEach(tile => {
if (isDashboardChartTileType(tile)) {
console.log('Chart:', tile.properties.savedChartUuid);
} else if (isDashboardMarkdownTileType(tile)) {
console.log('Markdown:', tile.properties.content);
}
});function hasChartsInDashboard(dashboard: DashboardDAO): boolean;
function getDefaultChartTileSize(
chartType: SavedChartType | string | undefined
): { h: number; w: number; x: number; y: number };Example:
import { hasChartsInDashboard, getDefaultChartTileSize, ChartKind } from '@lightdash/common';
if (hasChartsInDashboard(dashboard)) {
console.log('Dashboard contains chart tiles');
}
const tileSize = getDefaultChartTileSize(ChartKind.LINE);
// Returns: { h: 4, w: 6 } (default grid size)import {
type Dashboard,
type DashboardChartTile,
type DashboardMarkdownTile,
type DashboardFilterRule,
DashboardTileTypes,
FilterOperator,
UnitOfTime,
} from '@lightdash/common';
const dashboard: Dashboard = {
organizationUuid: 'org-uuid',
projectUuid: 'project-uuid',
uuid: 'dashboard-uuid',
name: 'Sales Performance Dashboard',
description: 'Key sales metrics and trends',
updatedAt: new Date(),
spaceUuid: 'space-uuid',
slug: 'sales-performance-dashboard',
dashboardVersionId: 1,
views: 0,
firstViewedAt: null,
pinnedListUuid: null,
pinnedListOrder: null,
tiles: [
{
uuid: 'tile-1',
type: DashboardTileTypes.MARKDOWN,
x: 0,
y: 0,
h: 2,
w: 12,
properties: {
title: 'Dashboard Overview',
content: '# Sales Performance\n\nTracking key metrics for Q4 2024.',
},
},
{
uuid: 'tile-2',
type: DashboardTileTypes.SAVED_CHART,
x: 0,
y: 2,
h: 4,
w: 6,
properties: {
savedChartUuid: 'revenue-chart-uuid',
title: 'Monthly Revenue',
},
},
{
uuid: 'tile-3',
type: DashboardTileTypes.SAVED_CHART,
x: 6,
y: 2,
h: 4,
w: 6,
properties: {
savedChartUuid: 'orders-chart-uuid',
title: 'Orders by Region',
},
},
],
filters: {
dimensions: [
{
id: 'date-filter',
label: 'Date Range',
target: { fieldId: 'orders.created_at' },
operator: FilterOperator.IN_THE_PAST,
values: [90],
settings: { unitOfTime: UnitOfTime.days },
tileTargets: {
'tile-2': { fieldId: 'orders.created_at' },
'tile-3': { fieldId: 'orders.created_at' },
},
},
],
metrics: [],
tableCalculations: [],
},
tabs: [
{ uuid: 'tab-1', name: 'Overview', order: 0 },
{ uuid: 'tab-2', name: 'Details', order: 1 },
],
};Converts a chart source type to the corresponding dashboard tile type.
/**
* Convert a chart source type to the corresponding dashboard tile type
* @param sourceType - The chart source type to convert
* @returns The corresponding dashboard tile type
*/
function convertChartSourceTypeToDashboardTileType(
sourceType: ChartSourceType
): DashboardTileTypes;Usage:
import { convertChartSourceTypeToDashboardTileType, ChartSourceType, DashboardTileTypes } from '@lightdash/common';
// Convert DBT explore chart to dashboard tile type
const tileType = convertChartSourceTypeToDashboardTileType(ChartSourceType.DBT_EXPLORE);
// Returns: DashboardTileTypes.SAVED_CHART
// Convert SQL chart to dashboard tile type
const sqlTileType = convertChartSourceTypeToDashboardTileType(ChartSourceType.SQL);
// Returns: DashboardTileTypes.SQL_CHARTValidates that selected tabs exist in the dashboard and throws an error if none of the selected tabs are valid.
/**
* Validates that at least one of the selected tabs exists in the dashboard
* @param selectedTabs - Array of tab UUIDs to validate, or null for all tabs
* @param dashboardTiles - Array of dashboard tiles containing tab information
* @throws ParameterError if none of the selected tabs exist in the dashboard
*/
function validateSelectedTabs(
selectedTabs: string[] | null,
dashboardTiles: DashboardTile[]
): void;Usage:
import { validateSelectedTabs } from '@lightdash/common';
// Validate that selected tabs exist
try {
validateSelectedTabs(['tab-1', 'tab-2'], dashboard.tiles);
console.log('Selected tabs are valid');
} catch (error) {
console.error('Invalid tabs selected:', error);
}
// null means all tabs are valid
validateSelectedTabs(null, dashboard.tiles); // Always succeeds