Dashboard framework comparison · Reviewed August 2026

Mercury vs Dash: Notebook Apps vs. Callback Framework

Mercury turns an existing analysis notebook into a dashboard without a separate component tree, callback graph, or frontend layout layer. For most notebook-based dashboards, that is the shorter path from result to a usable application.

Dash offers deeper application-level control. This comparison shows when that extra architecture is useful—and when Mercury’s notebook-first publishing model is a better fit.

hello.ipynb · Mercury
[1]
import mercury as mr
[2]
name = mr.TextInput(label="What is your name?")
[3]
mr.Markdown(f"## Hello {name.value}! 👋")
app.py · Dash
from dash import Dash, html, dcc, Input, Output, callback app = Dash() app.layout = html.Div([ dcc.Input( id="name", type="text", placeholder="What is your name?", ), html.Div(id="output"), ]) @callback( Output("output", "children"), Input("name", "value"), ) def greet(name): return f"Hello {name}! 👋" if name else "" if __name__ == "__main__": app.run(debug=True)

The short answer

Choose Mercury when you need a useful dashboard from an existing notebook—not a new callback-driven application architecture.

  • Keep calculations and charts in notebook cells.
  • Skip component IDs, Inputs, Outputs, and callbacks.
  • Apply a complete visual theme without frontend code.
  • Add a password-protected login with one server flag.
  • Choose managed cloud publishing or self-hosting.

Quick answer

Notebook-first or callback-first

Mercury keeps the notebook as the application source. Dash separates the interface into a component layout and an explicit callback graph.

Starting point

Mercury
Your existing Jupyter notebook (.ipynb)
Dash
A Python app with a component layout and callbacks

Reuse existing analysis

Mercury
Keep notebook calculations, charts, outputs, and narrative
Dash
Build an application layout around the reusable Python logic

Structure

Mercury
Widgets live directly in notebook cells; layout is provided
Dash
app.layout defines the UI; callback functions define interactions

Execution model

Mercury
Cells below a changed widget rerun
Dash
A callback runs when its declared Input changes

Callbacks

Mercury
None offered or needed
Dash
Explicit Input and Output wiring for interactive updates

Frontend layout code

Mercury
Not required for the standard application layout
Dash
Component tree defines the interface structure

Visual styling

Mercury
Theme, typography, sidebar, and app chrome configured with a compact config file
Dash
Component properties, stylesheets, and assets provide detailed frontend control

Password protection

Mercury
Built-in shared-password login with one server flag
Dash
Add HTTP Basic Auth with dash-auth, or use managed platform authentication

Advanced execution

Mercury
One reactive notebook model throughout
Dash
Clientside, background, async, and partial-update options

License

Mercury
Apache-2.0
Dash
MIT

Free hosting

Mercury
One public MLJAR Cloud app, or self-host with Docker
Dash
Self-host the open-source app

Managed platform

Mercury
One-click deployment from MLJAR Studio to MLJAR Cloud
Dash
Plotly Cloud or Dash Enterprise

Best fit

Mercury
Notebook-first dashboards, tools, reports, and chat
Dash
Component-based data apps with explicit interaction control

The starting point

Notebook cells or layout plus callbacks

A small greeting shows the structural difference without pretending that either framework needs complex business logic.

hello.ipynb · Mercury
[1]
import mercury as mr
[2]
name = mr.TextInput(label="What is your name?")
[3]
mr.Markdown(f"## Hello {name.value}! 👋")
app.py · Dash
from dash import Dash, html, dcc, Input, Output, callback app = Dash() app.layout = html.Div([ dcc.Input( id="name", type="text", placeholder="What is your name?", ), html.Div(id="output"), ]) @callback( Output("output", "children"), Input("name", "value"), ) def greet(name): return f"Hello {name}! 👋" if name else "" if __name__ == "__main__": app.run(debug=True)

Dash separates the component tree from the function that updates it, then connects them by component ID and property. That is more code here, but it provides fine-grained, traceable control as an application grows. Mercury keeps the widget beside the notebook logic and determines what reruns from cell position.

Execution model

Dash is explicit by design

Nothing updates merely because it appears later in the file. A callback declares the Input that triggers it and the Output it changes.

Dash connects component properties through @callback(Output(...), Input(...)). The function runs when its declared input changes, and its return value updates the declared output. This makes the interaction graph visible in code.

Mercury has no callback API. A widget’s .value is a regular Python value, and the cells below that widget rerun when it changes. Dash asks for more wiring; Mercury relies on notebook order. Dash’s explicitness is a deliberate tradeoff, not a flaw.

See how Mercury’s notebook model works
callbacks.py · Dash
@callback( Output("sales-chart", "figure"), Input("region", "value"), ) def update_chart(region): filtered = df if region == "All" else df[df.region == region] return px.bar(filtered, x="month", y="revenue")

The component properties and update function are linked explicitly.

Read Dash’s callback documentation

When Dash may fit better

More control for specialized production applications

Dash earns its additional complexity when a project genuinely needs browser-side callbacks, background job infrastructure, advanced grids, or enterprise operations.

Clientside callbacks

Run interaction logic in JavaScript inside the browser, avoiding a server round trip when the work belongs on the client.

Read the official documentation

Background callbacks

Move long-running Python work to a DiskCache or Celery-backed queue instead of occupying the web request worker.

Read the official documentation

Dash AG Grid

Build editable, filterable data grids. Advanced features such as pivoting and row grouping are available through AG Grid Enterprise.

Read the official documentation

Dash Enterprise

Add an organization-wide platform for deployment, app management, authentication, scaling, and production operations.

Read the official documentation

These capabilities matter for a narrower class of applications. If your goal is to share an existing notebook as a dashboard, Mercury avoids paying that architectural cost before you need it.

Mercury styles

Give the dashboard a polished design without frontend work

Use a ready-made style or configure a few theme tokens for your colors, typography, sidebar, navigation, and application surfaces.

Minimal Light theme applied to a Mercury prediction dashboard

Minimal Light

A clean, neutral application theme for reports and everyday dashboards.

Editorial Serif theme applied to a Mercury prediction dashboard

Editorial Serif

A warmer publication-style theme for research, reports, and narrative analysis.

Dark Ops theme applied to a Mercury prediction dashboard

Dark Ops

A high-contrast dark theme for operational dashboards and internal tools.

Customize a Mercury app
Mercury login screen asking for a password before opening a dashboard
Visitors sign in before they can open a password-protected Mercury dashboard.

Built-in access protection

Put the dashboard behind a password

A team dashboard does not need to be public. For a self-hosted Mercury app, add one flag when the server starts to show Mercury’s shared-password login.

mercury --pass=your-secret-here

The server flag provides one shared password. Paid MLJAR Cloud plans add private app capacity when you need individual access.

Dash is not missing password protection: the free dash-auth package adds HTTP Basic Auth in a few lines. Mercury’s advantage is that login can be part of the same notebook publishing and managed deployment flow.

Deployment

Publish from MLJAR Studio with one click

Send the notebook app directly to MLJAR Cloud without preparing a server, container, or deployment pipeline.

Free plan

Start with one public app

The MLJAR Free plan includes one public Mercury web app. Build the dashboard in a notebook, click deploy in MLJAR Studio, and share the generated URL without operating a server.

Deploy a Mercury app for free
Your choice

Upgrade or keep full control

Paid cloud plans add private app capacity. If your organization needs complete infrastructure control, deploy the same Mercury notebook on your own server with Docker.

Compare publishing limits

Decision guide

Publish the notebook, or build the application

Both produce interactive data apps in pure Python. Mercury takes the notebook as the source and adds the application layer around it. Dash is an application you write, with a callback graph you define explicitly.

Choose Mercury if

  • The analysis lives in a notebook and you want it to stay there—the notebook is the app, not a prototype you port.
  • You want widgets to rerun the cells below them instead of declaring Input and Output dependencies for each interaction.
  • The result reads as a document with controls: narrative, tables, and charts in order, not a layout of arranged components.
  • You want styling, login, and hosting handled as part of publishing rather than as three separate decisions.
  • The people maintaining it are analysts who edit notebooks, not developers who maintain a Python application package.

Choose Dash if

  • You need multi-page routing, URL-driven state, or deep-linkable views.
  • You want fine-grained partial updates—recompute only what a change affects instead of rerunning downstream cells.
  • You need clientside callbacks, background callbacks with a job queue, or long-running task patterns.
  • You want the component ecosystem: AG Grid, Leaflet, Cytoscape, Mantine, or your own React components.
  • You need custom CSS and element-level layout control, or must embed the app in an existing Python web service.
  • The app is a codebase—tested, reviewed as diffs, and deployed through your own CI.
  • Your organization is standardizing on Plotly’s commercial deployment and enterprise tooling.

The callback graph is the real trade. Dash makes every dependency explicit, which is more to write and gives precise control over what recomputes. Mercury infers execution from cell order, which is less to write and can rerun more than strictly necessary. For a notebook of moderate cost, that is a fair trade. For an app where a single expensive step must not rerun, explicit callbacks win.

Using MLJAR Studio? You can publish a notebook as a free public Mercury app directly from the editor. See how one-click publishing works

FAQ

Questions about Mercury and Dash

Do I need to write a callback for every interaction in Dash?+

For server-driven interactive updates, callbacks are Dash’s core model: you declare the component property that triggers the function and the property it updates. Dash also offers clientside callbacks and direct property updates for more specialized cases. Mercury has no callback API.

Which is better for a large, complex production dashboard?+

Dash is usually the stronger fit when the application needs explicit interaction control, background jobs, browser-side callbacks, advanced data grids, or multi-page routing. Mercury is a strong production fit when the notebook itself should remain the application source.

Can Dash run inside a Jupyter notebook?+

Yes. Dash 2.11 and later can run directly in Jupyter Notebook and JupyterLab, displaying inline by default. The app is still written as a Dash layout with callbacks; the notebook is the development environment rather than the application format.

Is Dash free?+

Dash core is MIT-licensed and free to self-host. Some surrounding products and features are commercial: Dash Enterprise is paid, and the enterprise feature set in Dash AG Grid requires an AG Grid Enterprise license.

Which has an easier learning curve?+

Mercury is generally simpler when you already work in Jupyter because widgets sit beside the analysis and need no callback wiring. Dash takes more structure upfront, but that explicit layout-and-callback model becomes valuable in large applications.

Can I protect a Mercury dashboard with a password?+

Yes. Start a self-hosted Mercury server with the --pass option to show a shared-password login before the dashboard opens. Private MLJAR Cloud apps with individual access are available on paid plans.

Can I customize how a Mercury dashboard looks?+

Yes. A compact config.toml controls the theme, typography, colors, navigation, sidebar, welcome page, and other application details. Mercury also provides ready-made configurations that you can use as starting points.

Can I deploy a Mercury dashboard without managing a server?+

Yes. MLJAR Studio provides one-click deployment of Mercury notebook apps to MLJAR Cloud. The free plan includes one public Mercury app; paid plans add private app capacity.

Turn the dashboard notebook into a complete app

Keep your analysis, add reactive controls, apply your style, protect access, and publish without managing a server.

pip install mercury