| name | shiny-python-dashboard |
| description | Build polished Shiny for Python dashboards and analytical apps. Use when creating or refactoring Shiny for Python apps, dashboards, KPI layouts, sidebar or navbar navigation, cards, value boxes, responsive grids, reactive filtering, charts, data tables, or when choosing between Core and Express APIs. |
Modern Shiny for Python Dashboards
Build professional Shiny for Python dashboards with Shiny's layout primitives, cards, value boxes, and reactive data flow. Keep this root file small: read it first, then load only the reference files that match the task.
Progressive loading
Do not treat this file as the full handbook. Use it as the routing layer.
After reading this file, load only the references you need:
| Task surface | Read this file |
|---|
| Page structure, sidebar vs navbar, responsive grids, fill behavior, branded navbar with per-tab icons | references/layout-and-navigation.md |
Cards, value boxes, accordions, toolbars, tooltips, summary tables with native render.DataTable | references/components.md |
Reactive graph design, @render.plot, Plotly brand template, DataGrid number formatting, empty-state handling | references/reactivity-and-rendering.md |
| Themes and brand palette, CSS spacing safety net, number formatting, data loading, project structure | references/styling-and-data.md |
| Icons, geographic outputs, map-library picker, lonboard / pydeck / Plotly map tiers | references/icons-and-maps.md |
| Choosing between Core and Express or translating from one to the other | references/core-vs-express.md |
If the task spans multiple surfaces, read multiple references. Example: a multi-tab KPI dashboard with Plotly charts should normally load layout, components, reactivity, and styling.
For a professional analytical dashboard, assume the task spans layout, components, reactivity, and styling unless the user asks for a tiny example. Most benchmark failures come from treating these as optional.
Default routing
Use these defaults unless the prompt clearly points elsewhere:
- If the prompt names 3 or more analytical sections such as Performance, Patient Flow, Staffing, or Outcomes, default to
ui.page_navbar() and read references/layout-and-navigation.md.
- If the app is one workflow with one shared filter set, default to
ui.page_sidebar() and read references/layout-and-navigation.md.
- If the app has a prominent map, read references/icons-and-maps.md before writing code.
- If the app has any chart card, table card, KPI card, local display option, per-card filter, tooltip, popover, or action button, read references/components.md before writing code.
- If the user asks for Core vs Express guidance, or is translating an R or old Python app, read references/core-vs-express.md first.
Sensible dashboard defaults
Use this content hierarchy by default:
- KPI row at the top.
- Charts and maps in the middle, with per-card toolbars for local controls.
- Detailed table at the bottom, ideally with a toolbar for search/reset/export/display controls when relevant.
Use these component defaults unless the prompt conflicts:
full_screen=True on charts, maps, and tables.
ui.layout_column_wrap() for uniform KPI cards.
ui.layout_columns() when proportions matter.
- One shared filtered dataset per page or section via
@reactive.calc.
- One chart per card.
ui.toolbar() inside card headers for secondary controls instead of growing the sidebar.
Quick decisions
Use these shortcuts to stay consistent:
- Need the fastest path to a production-feeling app: navbar layout, default or clean light theme, tab icons, Plotly white template, one card per chart.
- Need a geographic view: read references/icons-and-maps.md and use the dependency-safe Plotly map pattern unless the app already has a declared richer map stack.
- Need a polished summary table: read references/components.md and prefer native
render.DataTable.
- Need maintainable server logic: read references/reactivity-and-rendering.md and centralize filtering in
@reactive.calc.
- Need translation guidance: read references/core-vs-express.md.
- Need local chart/table controls: use
ui.toolbar() in ui.card_header() instead of adding more global sidebar controls.
Avoid common failure modes
- Do not reference a stylesheet file that does not exist. Prefer
ui.tags.style(...) instead.
- Do not let KPI rows stretch edge to edge or exceed 4 cards before wrapping.
- Do not cram 3 or more serious charts into one row.
- Do not put multiple Matplotlib charts into one render function.
- Do not leave cards untitled.
- Do not leave numeric columns unformatted in tables.
- Do not use a map when geography is incidental to the question.
- Do not ignore the provided CSV or replace it with a package sample dataset.
- Do not leave a page that appears to render but shows errors, spinners, blank cards, or all-zero KPIs.
- Do not put every control in the sidebar. Use card toolbars for local display controls so the sidebar stays focused on global filters.
- Do not let any chart fall back to default Plotly or Matplotlib color cycles. Every
px.* call must include color_discrete_sequence=BRAND_SEQUENCE (or a slice of BRAND_COLORS). Every Matplotlib ax.bar/barh/hist/scatter must pass an explicit color= using BRAND_COLORS or BRAND_SEQUENCE. Defining the palette is not enough — you must pass it at every call site.
- Do not reuse the same output IDs (like
kpi_listings, plot_price) when copying layout containers or value boxes across different tabs or sidebars. Every output in a Shiny application must have a globally unique ID. Duplicate output IDs cause client-side rendering conflicts and silent data rendering failures.
- Do not use chart colors that clash with your page theme. If using a custom theme (e.g.
bs_theme(primary="#ff5a5f")), define BRAND_COLORS["primary"] = "#ff5a5f". If using the default Shiny theme (preset="shiny"), define your primary chart color as #007bc2, success color as #5cb85c, warning color as #f0ad4e, and danger color as #d9534f so the plots match the buttons, value boxes, and navigation headers exactly.
Minimal execution order
When implementing a dashboard, follow this order:
- Choose page structure.
- Choose theme. Define
BRAND_COLORS and BRAND_SEQUENCE at the top of the application script (see styling reference). Register the Plotly brand template with pio.templates.default = "plotly_white+brand". For Matplotlib, pass color=BRAND_COLORS["primary"] or color=BRAND_SEQUENCE[:n] on every chart call.
- Define the shared filtered dataset.
- Build the KPI row.
- Add chart and map cards with at least one useful toolbar across the dashboard.
- Add the summary or drill-down table.
- Add small CSS only if needed.
- Validate data source, empty states, formatting, startup safety, and screenshots for every tab.
Final quality gate
Before considering a dashboard done, check these items:
- The app reads the requested dataset path and no unrelated sample dataset is imported.
- Every tab/page has at least one meaningful rendered artifact: KPI, chart, map, table, or narrative summary.
- No card shows a traceback, red render error, permanent spinner, empty gray output, or accidental all-zero/N/A summary.
- At least one card uses
ui.toolbar() for a local control or info/action button when Shiny >= 1.6 is available.
- The initial default filters produce non-empty charts and tables.
- A browser screenshot of each tab looks like a professional dashboard, not just a technically launched app shell.
- Every chart uses
BRAND_COLORS or BRAND_SEQUENCE — no default Plotly rainbow, Matplotlib tab10, or Set2 cycles are visible. Bar charts, histograms, scatter plots, and pie/donut charts must all use the brand palette.
Reference files