A maintainable, object-oriented framework for creating consistent Streamlit charts using Plotly.
This repository demonstrates a design pattern for Streamlit applications where:
- Charts are Objects: Defined as classes inheriting from
BaseStreamlitChart. - Logic is Encapsulated: Data filtering, aggregation, and styling happen inside the class.
- Styles are Consistent: A central
ChartStylesconfiguration ensures specific design systems (fonts, colors) are applied globally, while allowing specific overrides. - Backend: Uses Plotly for rich interactivity.
The Abstract Base Class (ABC). It handles:
- Filtering: Automatically renders Streamlit widgets for registered filters.
- Aggregation: (Optional) Groups and aggregates raw data (e.g., Sum
CostbyDate) before plotting. - Styling: Applies Plotly layout templates.
Defines the default "Look and Feel".
- Edit
DEFAULTSto change the global theme (font, margins, templates).
Contains concrete chart implementations (e.g., CostBarChart, TimeSeriesChart).
- Implement the
generate_chart()method to return ago.Figure.
pip install -r requirements.txtstreamlit run app.py- The advanced demo loads a semantic model from
models/star_schema.yamlthat declares fact, dimensions, joins, measures, and default filter fields. - Shared filters in the sidebar apply across all charts; field wells let you choose dimension fields for X/Color and a measure for Y without touching code.
- Joins are cached and will run through DuckDB when available for faster star-schema workflows; otherwise pandas merges are used.
Subclass BaseStreamlitChart and implement generate_chart:
from src.base_chart import BaseStreamlitChart
import plotly.express as px
class MyChart(BaseStreamlitChart):
def generate_chart(self):
# self.get_data() returns the Filtered & Aggregated dataframe
return px.bar(self.get_data(), x="category", y="value")Pass raw data and let the chart aggregate it:
# Raw data has many rows per date
chart = MyChart(
data=raw_df,
group_by=["date"],
agg_funcs={"value": "sum"}
)
chart.render()This framework was originally designed with Altair but switched to Plotly for better interactivity and mutable object handling. See plotly_vs_altair.md for a detailed comparison.