How to Build a Dashboard in Python Without JavaScript
Build a runnable Reflex dashboard with a region filter, revenue chart, summary, and table. Add linked XY charts, pandas uploads, and custom layouts in Python.

You can build an interactive dashboard in Python with Reflex: define the interface with components, keep interaction state in a Python class, and connect controls to event handlers. This walkthrough builds a region filter that updates a revenue chart, total, and table together. It runs on sample data without a database or API key.
The same approach can support analytics, editable internal tools, or a dashboard with a chat or model-review panel. You control the layout and styling instead of starting from a fixed dashboard template. For chart selections that filter other views, continue with the linked XY charts tutorial.
Set up a Reflex app
Follow the installation guide to create a blank project. In a new directory, the basic uv workflow is:
Choose a blank app when prompted. Replace the generated app module inside the app package with the complete code below. Keep the generated rxconfig.py and its app name.
The example styles standard HTML elements with Tailwind classes. In rxconfig.py, keep your generated app name and include rx.plugins.TailwindV4Plugin() in the plugins list. If your blank template already includes it, keep that entry. See the Tailwind setup guide for the complete configuration.
Build the filter, chart, and table
The sample has two regions and two months. Filtering changes which records contribute to the monthly totals. The chart and table use the same summary, so their values stay consistent.
ExpandCollapse
Run the app:
Open the URL printed by the server. With All selected, the total is $630, with January at 210 and February at 420. Choose North to see $300 and monthly values of 120 and 180. Choose South to see $330 and values of 90 and 240.
This small example uses Reflex's Recharts components. The linked-chart example uses XY and demonstrates selecting chart points to filter another chart and a table.
How the dashboard updates
The select control sends its value to choose_region. The handler validates that value and updates region. The computed monthly_revenue and total_revenue values then supply the chart, table, and summary. The event does not rerun the complete Python page definition.
The aggregation is an ordinary Python function, so you can test it separately or replace it with your own analysis. The sample is intentionally tiny. For a large dataset, filter and aggregate in a suitable backend service or database and send the UI only the results it needs.
Each browser session has its own interaction state. Selecting North in one session does not automatically select it for another user. If multiple users need shared live data, define a shared data source and a refresh or subscription strategy deliberately.
Add linked charts, pandas, or other application features
Choose the next guide around the interaction you need:
| Requirement | Implementation to use |
|---|---|
| Select points to filter other views | Linked XY charts and cross-filtering |
| Upload, analyze, and download CSV data | Pandas data app |
| Add chat alongside dashboard data | Streaming chat tutorial |
| Collect model inputs and review outputs | Model and media interfaces |
| Combine charts with operational forms | Dashboards and internal tools |
These workflows can share a layout and application state. Authorization, durable storage, and provider-specific integrations remain application design decisions.
Customize the layout and appearance
Use stacks and grids to arrange content, CSS properties to control appearance, and responsive values to adapt it to different screens. The example sets a maximum content width and increases padding on larger screens. You can replace the layout with a sidebar, tabs, a details panel, or a multi-page application.
When an existing component does not cover your interaction, wrap a React component and define its props and event mapping. Most work with the existing Reflex components stays in Python; creating some integrations requires understanding the underlying JavaScript component.
Connect real data and background work
Put database queries and API calls behind application functions or services. Keep credentials on the backend, use parameterized queries, apply authorization before returning records, and define timeout and error behavior. The database guide covers Reflex's database integration; you can also call compatible Python data clients from backend code.
For slow I/O, use an async client or an appropriate worker. A background event can allow other events to proceed, with async with self controlling state access. Release that lock while waiting on a service. A blocking request or CPU-heavy computation still needs an execution strategy; adding async or yield does not make it nonblocking.
A background task is not automatically a durable job queue. For scheduled refreshes or jobs that must survive a restart, select an appropriate scheduler, queue, and storage service. See performance and execution for these boundaries.
Deploy and verify the application
Reflex generates and builds a frontend as part of preparing an application for production. You author the app in Python, while the deployed system includes browser assets and a Python backend.
Follow the deployment quick start for Reflex Cloud, or the self-hosting guide for your infrastructure. Configure secrets, networking, state storage, and database access for that environment. Before release, test authorization, empty and failed data loads, multiple sessions, narrow screens, and the expected workload.
How this compares with Streamlit and Dash
Streamlit and Dash can also build interactive dashboards in Python. A dropdown that updates multiple charts does not inherently require JavaScript in either framework. Dash uses callbacks with inputs and outputs; Streamlit supports script reruns and fragments for more focused updates.
Evaluate Reflex when you want the dashboard inside a custom application composed from Python components, state, and event handlers. Compare the real screen and workflow in each candidate. Production readiness and performance depend on that implementation and deployment, rather than a framework name alone. The framework comparison hub provides a broader comparison.
Written by
FAQ
Can Reflex link charts and update a table from the same selection?
Yes. Store the selection in shared application state and derive each view from it. The XY tutorial demonstrates a scatter selection updating a bar chart and table, including empty selections and reset behavior.
Can I use pandas in a Reflex dashboard?
Yes. Run pandas operations in backend Python code and return the data needed by the UI. The pandas tutorial demonstrates CSV upload, filtering, grouped summaries, and download while keeping the complete dataset out of frontend state.
Do I need JavaScript to build this dashboard?
No. The complete example above defines its UI, event handler, aggregation, and styling in Python. Integrating an unwrapped React component may require additional knowledge of its JavaScript API.
Will every user see the same filter selection?
No. Ordinary Reflex interaction state is session-specific. Use a shared data service and explicit synchronization when the application requires users to see shared updates.
Is Reflex faster than Streamlit or Dash?
This walkthrough does not establish that comparison. Measure equivalent applications, separating initial load, warm interactions, concurrent sessions, and backend work. Use each framework's supported execution and caching controls.


