Integration Patterns
Common patterns and best practices for building dashboards.
Publisher/Subscriber Pattern
Blocks publish state changes and other blocks subscribe to react.
Flow:
ControlPanelBlock → publishes → StateManager → notifies → TypedChartBlock
→ notifies → get_metric_row()
Example:
from dashboard_lego.blocks import get_metric_row, TypedChartBlock, ControlPanelBlock, Control
# Publisher: Control Panel
# Use transform__ prefix for automatic routing to transform stage
control_panel = ControlPanelBlock(
block_id="filters",
datasource=datasource,
title="Filters",
controls={"transform__category": Control(...)}
)
# Publishes: "filters-transform__category"
# Subscribers: Charts and Metrics
chart = TypedChartBlock(
block_id="chart1",
datasource=datasource,
plot_type='bar',
plot_params={'x': 'Product', 'y': 'Sales'},
subscribes_to="filters-transform__category"
)
metrics, row_opts = get_metric_row(
metrics_spec={
'total_sales': {
'column': 'Sales',
'agg': 'sum',
'title': 'Total Sales',
'color': 'success'
}
},
datasource=datasource,
subscribes_to="filters-transform__category"
)
Multi-State Subscriptions
A block can subscribe to multiple state sources.
Example:
# Multiple publishers
date_filter = ControlPanelBlock(
block_id="date_filter",
datasource=datasource,
title="Date Range",
controls={"date_range": Control(...)}
)
category_filter = ControlPanelBlock(
block_id="category_filter",
datasource=datasource,
title="Category",
controls={"category": Control(...)}
)
# Subscriber to multiple states
chart = TypedChartBlock(
block_id="multi_chart",
datasource=datasource,
title="Filtered Analysis",
plot_type='bar',
plot_params={'x': 'Product', 'y': 'Sales'},
subscribes_to=[
"date_filter-date_range",
"category_filter-category"
]
)
Theme Customization Pattern
Apply consistent theming across all components.
Example:
from dashboard_lego.core.theme import ThemeConfig, ColorScheme, Typography
# Create custom theme
theme = ThemeConfig.custom_theme(
name="corporate",
colors=ColorScheme(
primary="#003366",
secondary="#6699CC",
success="#009966",
background="#f5f5f5"
),
typography=Typography(
font_family="'Arial', sans-serif",
font_size_base="16px"
)
)
# Apply to page
page = DashboardPage(
title="Corporate Dashboard",
blocks=my_blocks,
theme_config=theme
)
Layout Composition Pattern
Build complex layouts from simple presets.
Example:
from dashboard_lego.presets.layouts import (
kpi_row_top,
two_column_8_4,
three_column_4_4_4
)
# Compose complex layout
layout = kpi_row_top(
kpi_blocks=[kpi1, kpi2, kpi3, kpi4],
content_rows=[
# Row 1: Main chart with sidebar
two_column_8_4(main=main_chart, side=filter_panel),
# Row 2: Three comparison charts
three_column_4_4_4(a=chart1, b=chart2, c=chart3),
# Row 3: Full-width table
[table_block]
]
)
page = DashboardPage(
title="Complex Dashboard",
blocks=layout
)
Data Processing Pipeline Pattern (v0.15)
Staged data processing with DataBuilder + DataTransformer for optimal caching.
Pipeline Flow:
Control Panel → Params → DataSource → Build → Transform → Blocks
↓ ↓ ↓
Classifier Cache Cache
Example:
from dashboard_lego.core import DataSource, DataBuilder, DataTransformer
# Step 1: Define DataBuilder
class SalesDataBuilder(DataBuilder):
def __init__(self, file_path: str):
super().__init__()
self.file_path = file_path
def build(self, params):
df = pd.read_csv(self.file_path)
df['Revenue'] = df['Price'] * df['Quantity']
df['Date'] = pd.to_datetime(df['Date'])
return df
# Step 2: Define DataTransformer
class SalesTransformer(DataTransformer):
def transform(self, data, **params):
df = data.copy()
# Use transform__ prefix in control names for automatic routing
if 'transform__category' in params:
cat = params['transform__category']
if cat != 'All':
df = df[df['Category'] == cat]
return df
# Step 3: Create datasource (uses default classifier)
# Default classifier automatically routes:
# - transform__* params → transform stage
# - build__* params → build stage
# - other params → build stage (default)
datasource = DataSource(
data_builder=SalesDataBuilder("sales.csv"),
data_transformer=SalesTransformer(),
cache_ttl=600
)
Parameter Naming Convention (v0.15+):
Control names should use explicit prefixes to route parameters to the correct pipeline stage:
``transform__<name>``: Routes to transform stage (filtering/aggregation)
``build__<name>``: Routes to build stage (data loading/preprocessing)
No prefix: Defaults to build stage
The default classifier automatically parses these prefixes. No custom classifier needed.
Example Control Panel:
control_panel = ControlPanelBlock(
block_id="filters",
datasource=datasource,
title="Filters",
controls={
"transform__category": Control(...), # → transform stage
"transform__min_price": Control(...), # → transform stage
"build__window_size": Control(...), # → build stage
}
)
Benefits:
Performance: Changing filters only triggers transform stage
Clarity: Each component has one responsibility
Testability: Test builder and transformer independently
Reusability: Same components can be used in multiple dashboards
Simplicity: No custom classifier needed - use naming convention
Cache Sharing (v0.15.2):
Cache objects are automatically shared across datasource instances to prevent duplicate builds:
Same cache_dir: Multiple datasources with identical
cache_dirpaths share cacheIn-memory: All
cache_dir=Nonedatasources share single global in-memory cacheStage1 (Build) optimization: When using
with_transform_fn(), the derived datasource reuses the parent’s cache →build()executes only once
Example:
from dashboard_lego.core import DataSource, DataBuilder
# Create main datasource
main_ds = DataSource(
data_builder=MyDataBuilder(),
cache_dir=None # In-memory cache
)
# Create derived datasource with additional transform
filtered_ds = main_ds.with_transform_fn(
lambda df: df[df['Category'] == 'A']
)
# Cache is shared automatically:
assert main_ds.cache is filtered_ds.cache # True!
# Stage1 (builder.build) executes only ONCE:
data1 = main_ds.get_processed_data() # Triggers build()
data2 = filtered_ds.get_processed_data() # Reuses cached build, only applies filter
# Result: No duplicate expensive data loading/processing
When cache sharing happens:
Explicit matching:
DataSource(..., cache_dir="/path")→ all instances with same path share cacheIn-memory default:
DataSource(..., cache_dir=None)→ all in-memory instances share cacheDerived datasources:
ds.with_transform_fn(...)→ automatically inherits parent’s cache
Quick Dashboard Pattern
The quick_dashboard() factory enables rapid prototyping in Jupyter notebooks,
Python scripts, and anywhere Dash runs, with minimal code. Supports simple mode
(DataFrame + card specs) and advanced mode (pre-built blocks).
Smart Layout Algorithm:
The factory uses an intelligent layout algorithm optimized for notebook readability:
Metrics are compact: All metrics grouped in single row using
get_metric_row()Charts need space: Maximum 2 charts per row
Vertical scroll friendly: Optimized for notebook viewing
Layout Examples:
2M + 2C→ metrics_row + [chart1_50, chart2_50]1M + 3C→ metrics_row + [chart1_full] + [chart2_50, chart3_50]4M + 0C→ metrics_row (all 4 in one compact row)0M + 3C→ [chart1_full] + [chart2_50, chart3_50]
Simple Mode:
For quick exploration with 1-4 cards:
from dashboard_lego.utils.quick_dashboard import quick_dashboard
import pandas as pd
# Load data
df = pd.DataFrame({
'Product': ['Widget', 'Gadget', 'Tool', 'Device'],
'Sales': [100, 200, 150, 180],
'Revenue': [1000, 2000, 1500, 1800]
})
# Create dashboard with card specs
app = quick_dashboard(
df=df,
cards=[
{
"type": "metric",
"metric_spec": {
"column": "Revenue",
"agg": "sum",
"title": "Total Revenue",
"color": "success"
}
},
{
"type": "chart",
"plot_type": "bar",
"plot_params": {"x": "Product", "y": "Sales"},
"title": "Sales by Product"
},
{
"type": "text",
"content_generator": lambda df: "## Sales Dashboard\nQuick analysis"
}
],
title="Sales Dashboard",
theme="lux"
)
# Run inline (requires jupyter-dash)
app.run_server(mode='inline')
# Or open in new browser tab
app.run_server(debug=True)
Card Specification Reference:
- Metric Card:
Required:
type="metric",metric_spec(dict withcolumn,agg,title)Optional in metric_spec:
color(success, info, primary, danger, warning, secondary),dtypeExample:
{"type": "metric", "metric_spec": {"column": "Sales", "agg": "sum", "title": "Total Sales", "color": "success"}}
- Chart Card:
Required:
type="chart",plot_type,plot_params(dict withx,y),titleOptional in plot_params:
color,sizeExample:
{"type": "chart", "plot_type": "bar", "plot_params": {"x": "Product", "y": "Sales"}, "title": "Sales Chart"}Plot types: bar, line, scatter, histogram, box, violin, pie, etc.
- Text Card:
Required:
type="text",content_generator(callable:df -> Component | str)Supports: Markdown formatting (return string to render as Markdown)
Example:
{"type": "text", "content_generator": lambda df: "## Analysis\n\nKey insights..."}
Advanced Mode:
For full control with pre-built blocks:
from dashboard_lego.blocks import SingleMetricBlock, TypedChartBlock
from dashboard_lego.core import DataSource, DataBuilder
from dashboard_lego.utils import quick_dashboard
# Create custom datasource
class MyDataBuilder(DataBuilder):
def build(self, params):
# Your custom data loading logic
return pd.read_csv("data.csv")
datasource = DataSource(data_builder=MyDataBuilder())
# Create custom blocks with full configuration
blocks = [
SingleMetricBlock(
block_id="metric1",
datasource=datasource,
metric_spec={
'column': 'Revenue',
'agg': 'sum',
'title': 'Total Revenue',
'color': 'success'
}
),
TypedChartBlock(
block_id="chart1",
datasource=datasource,
plot_type="bar",
plot_params={"x": "Product", "y": "Sales"},
title="Sales Chart"
)
]
# Create dashboard from blocks
app = quick_dashboard(blocks=blocks, title="Custom Dashboard")
app.run_server(debug=True)
Installation:
# Install with Jupyter support
pip install dashboard-lego[jupyter]
# Or install jupyter-dash separately
pip install jupyter-dash
Features:
Zero disk I/O: Uses in-memory data pipeline (
cache_ttl=0)Smart layout: Metrics grouped in compact row, charts max 2 per row
Theme support: All Bootstrap themes supported (lux, dark, light, cyborg, etc.)
Universal: Works in Jupyter, Python scripts, anywhere Dash runs
Type safety: Validates card specifications at runtime
Export Pattern
Export dashboard figures for static reports and notebooks.
Single Figure:
chart = TypedChartBlock(
block_id="chart",
datasource=datasource,
plot_type="scatter",
plot_params={"x": "X", "y": "Y"}
)
fig = chart.get_figure()
fig.write_html("chart.html")
Layout Export:
layout = [[chart1, chart2], [chart3]]
fig = export_layout_to_figure(layout, title="Dashboard")
fig.write_html("dashboard.html")
See Exporting Figures for complete documentation.
IPython Magic Commands
For even faster dashboard creation in Jupyter notebooks, Dashboard Lego provides IPython magic commands that reduce code to a single line.
Loading the Extension:
%load_ext dashboard_lego.ipython_magics
Magic 1: %dashboard (Line Magic)
Create dashboard in one line:
# Syntax
%dashboard df --metric column agg title [color] --chart plot_type x y title
# Example
%dashboard df -m Sales sum "Total Sales" success -c bar Product Sales "Sales Chart"
# Short flags: -m (metric), -c (chart), -x (text), -t (title), -p (port)
Magic 2: %dashboard_theme
Set default theme for future dashboards:
# Set theme
%dashboard_theme cyborg
# View current theme and list all available
%dashboard_theme
Magic 3: %%dashboard_cell (Cell Magic)
Multi-line YAML-like configuration:
%%dashboard_cell
dataframe: df
title: "Sales Analytics"
theme: dark
port: 8050
cards:
- metric: Revenue, sum, "Total Revenue", success
- metric: Profit, sum, "Total Profit", warning
- chart: bar, Product, Sales, "Sales Chart"
- text: "## Summary\n\nKey insights..."
Comparison:
Traditional API (3 lines):
app = quick_dashboard(df=df, cards=[...])
app.run(port=8050)
Magic command (1 line):
%dashboard df -m Sales sum "Total" -c bar Product Sales
Use Cases:
Quick exploration and prototyping
Interactive data analysis sessions
Minimal typing for ephemeral dashboards
Teaching and demonstrations
Placeholders Guide
Dashboard Lego supports {{placeholders}} in specific contexts for dynamic content. This guide explains where placeholders work and where they don’t.
Supported Contexts:
Plot Parameters (``plot_params``): Dynamic column selection and visual encoding
Plot Title (``plot_title``): Dynamic chart title inside the plot
Control Properties: Dynamic control options and values
Unsupported Contexts:
Card Title (``title``): Static card header (no placeholders)
Text Content: Static markdown content
Best Practices:
Use ``plot_title`` for Dynamic Chart Titles:
# ✅ Good: Dynamic chart title - type: chart title: "Session Analysis" # Static card header plot_title: "Analysis @ step={{window_step_selector}}" # Dynamic chart title # ❌ Avoid: Placeholders in card title - type: chart title: "Analysis @ step={{window_step_selector}}" # Won't work
Use ``plot_params`` for Dynamic Visual Encoding:
# ✅ Good: Dynamic visual properties - type: chart plot_type: scatter x: session_length y: max_idle color: "{{metric_selector}}" # Dynamic color size: "{{size_selector}}" # Dynamic size
Use Variable Interpolation for Control Options:
# ✅ Good: Dynamic control options environment: - metric_options cards: - type: control_panel controls: - name: metric_selector type: dropdown options: $metric_options # Variable interpolation value: "{{default_metric}}" # Placeholder for default
Common Patterns:
Pattern 1: Interactive Scatter Plot
cards:
- type: control_panel
title: "Select Metrics"
controls:
- name: color_metric
type: dropdown
options: $metric_options
value: "n_sessions"
- name: size_metric
type: dropdown
options: $metric_options
value: "median_session_length"
- type: chart
title: "Session Analysis" # Static card title
plot_type: scatter
x: session_length
y: max_idle
color: "{{color_metric}}" # Dynamic color
size: "{{size_metric}}" # Dynamic size
plot_title: "Sessions vs Idle @ {{color_metric}}" # Dynamic plot title
Pattern 2: Parameterized Analysis
cards:
- type: control_panel
title: "Analysis Parameters"
controls:
- name: window_step
type: slider
min: 1
max: 10
value: 1
- type: chart
title: "Parameter Analysis" # Static card title
plot_type: scatter
x: session_length
y: max_idle
plot_title: "Analysis @ step={{window_step}}" # Dynamic plot title
Troubleshooting:
Problem: Placeholder not resolving
- Symptoms: {{placeholder}} appears literally in output
- Solutions: Check placeholder name matches control name exactly, ensure control is subscribed to the chart, verify placeholder is in supported context
Problem: Card title not updating
- Symptoms: Card title stays static when controls change
- Solutions: Use plot_title instead of title for dynamic content, keep title static for card header
Problem: Control not affecting chart
- Symptoms: Changing controls doesn’t update chart
- Solutions: Check subscribes_to includes correct state IDs, verify control names match placeholder names, ensure control publishes state changes