Dash.jl: building analytic web apps in Julia without JavaScript
Dash for Julia - A Julia interface to the Dash ecosystem for creating analytic web applications in Julia. No JavaScript required.
At a glance
- What is it?
- Dash.jl is a Julia port of Plotly's Dash, letting you build an interactive dashboard where the callbacks are ordinary Julia functions and the components are named constructors, with the React and Plotly.js machinery running in the browser. It is a port rather than a reimplementation, and the README is candid about its status and about what it borrows from the Python original.
- Who is it for?
- Dash.jl fits a Julia team that wants a dashboard without writing JavaScript and without leaving the Julia process for the analysis, and that is willing to accept the port's rough edges. It does not fit a team that needs the full Dash component library, since the components are generated alongside the Python and R ones and lag behind, and it does not fit a production service that needs a maintained release cadence, since the newest tagged version is v1.5.0 from 2024-01-05.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 141 days ago.
- What is it written in?
- Mainly Julia, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the port actually is
Dash.jl is a Julia interface to the Dash ecosystem for creating analytic web applications in Julia, and the README states the promise plainly: no JavaScript required.
The description also says the source is built on top of Plotly.js, React and HTTP.jl, and that Dash ties modern UI elements like dropdowns, sliders, and graphs directly to your analytical Julia code. So the division of labour is the same as in the Python original. The browser runs a React application with Plotly.js rendering the charts, HTTP.jl serves the app and the callback endpoints, and the Julia code you write is the part that does the analysis.
What the port changes is the authoring language and the syntax. Components become named constructors such as html_div and dcc_graph rather than dash.html.Div and dash.dcc.Graph, and callbacks become a function call with a do block rather than a decorator.
The Project Status section is the part to read before anything else. Julia components can be generated in tandem with Python and R components, and the project carries a banner saying it is maintained by the Plotly Community rather than by Plotly itself. The default branch is dev, not master, and the last push to the repository was on 2026-06-04, which is the branch where the work is actually happening.
The releases tell the other half of the story. The most recent tagged versions are v1.5.0 from 2024-01-05, v1.4.0 from 2023-10-10 and v1.3.0 from 2023-07-12. So the tagged releases are two and a half years old, while the dev branch has seen recent work. That split is the single most important practical fact about this project.
Installation, and the difference between the two channels
There are two install paths and the README explains what each gives you.
To install the most recently released version:
pkg> add DashAnd to install the latest stable development version instead:
pkg> add Dash#devThat second form is the one to note. Given that the newest tag is from January 2024 and the dev branch is the active one, the released version and the current code are quite far apart, and a user who needs current components has to take the development branch.
The package is a standard Julia package with a Project.toml at the repository root. The repository also has an Artifacts.toml, which is the Julia mechanism for declaring downloadable binary artefacts that the package manages for you, and a .gitmodules file, which means some dependencies are vendored as submodules rather than pulled from the registry.
The rest of the repository layout is a conventional Julia package: src/ for the source, test/ for the tests, docs/ for the documentation, build/ for build configuration, gen_resources/ for the generated resources, and at the root a CHANGELOG.md, a CONTRIBUTING.md, a CODE_OF_CONDUCT.md and a .markdownlint.yml. The markdownlint configuration is a small detail with a real meaning, because the README itself is a large comparison document full of code blocks, and linting it catches the kind of formatting drift that makes a long README unreadable.
The CI setup is visible in the badges: a GitHub Actions workflow for the Julia tests and a CircleCI build, both on the dev branch.
A first application, and the do-block layout
The basic application example is short, and the layout syntax is the part worth understanding.
using Dash
app = dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])
app.layout = html_div() do
html_h1("Hello Dash"),
html_div("Dash.jl: Julia interface for Dash"),
dcc_graph(id = "example-graph",
figure = (
data = [
(x = [1, 2, 3], y = [4, 1, 2], type = "bar", name = "SF"),
(x = [1, 2, 3], y = [2, 4, 5], type = "bar", name = "Montréal"),
],
layout = (title = "Dash Data Visualization",)
))
end
run_server(app)The layout is assigned to app.layout as a tree of component calls, and the do-block form is how nesting is expressed. A component with children can be written as html_div("Simple text", id = "my-id"), or with a children maker function passed in, which is what the do syntax produces.
The figure is a NamedTuple with data and layout keys, and the data is a vector of NamedTuples with x, y, type and name. That is a direct consequence of the port's JSON layer, and the README explains it in the JSON section: Dash apps transfer data between the browser and the Julia process in JSON, and Dash.jl uses JSON3.jl for serialization and deserialization, with vectors and tuples converted to JSON arrays and dicts and named tuples to JSON objects.
The server runs on the standard Dash port, and the README says to go to http://127.0.0.1:8050 in a browser to view the app.
Callbacks, states, and the function signature rule
The interactivity model is the part a Julia user will feel most, because it is a function signature rather than a decorator.
callback!(app, Output("my-div", "children"), Input("my-id", "value")) do input_value
"You've entered $(input_value)"
endThe README states the rules for callbacks. You register them with the callback! function. The outputs and inputs, and states, of a callback can be Output, Input, State objects or splats and vectors of these objects. And the callback function must have the signature (inputs..., states...), and provide a return value with the same number of elements as the number of Outputs to update.
The last rule is the one that will bite first. A callback with two outputs has to return a tuple of two values, and the order has to match the order of the Output declarations, which is the same rule as in the Python original but without the decorator to hold it for you.
State is the difference from a simple two-way binding. A State is a value the callback can read but that does not itself trigger the callback, which is how you read the current value of a control without causing a round trip.
callback!(app,
Output("my-div","children"),
Output("my-div2","children"),
Input("my-id", "value"),
State("my-id", "type")) do input_value, state_value
return ("You've entered $(input_value) in input with type $(state_value)",
"You've entered $(input_value)")
endNote the ordering in that call: both Outputs are declared first, then the Input, then the State, and the function signature takes the input value first and the state value second. The README's phrasing of the signature as (inputs..., states...) is the summary of that convention.
The Python comparison, and the naming rules it reveals
The README devotes a long section to a side-by-side comparison with the original Python syntax, and that section is the best available specification of the port's conventions.
On component naming, Python uses dash.html.Div, dash.dcc.Graph and dash.dash_table.DataTable, while Dash.jl uses html_div, dcc_graph and dash_datatable. The rule is mechanical: the dotted path becomes a single lowercase name with the parts run together.
On component creation, functions for declaring components have keyword arguments, the same as in Python, and the example is html_div(id = "my-id", children = "Simple text"). For components which declare children, two additional signatures are available, one taking children positionally with keyword arguments, and one taking a children maker function. That is what makes the do syntax work, and it is why html_div("Simple text", id = "my-id") is valid for a simple element.
On application and layout, Python assigns dash.Div children as a list, while Dash.jl assigns a do-block. The comparison is repeated for callbacks, showing the Python decorator form with Output, Input and State against the Julia callback! call with a do block.
The section is not documentation for its own sake. It exists because the component generators and the API surface are produced alongside the Python and R versions, and a Julia developer who knows Dash in Python already has a working mental model, which is the fastest way to read this port.
Where Dash.jl is the wrong choice
Three cases point elsewhere. The first is a project that needs the full Dash component library today. The components are generated in tandem with the Python and R ones, which means the Julia set lags by however long the generation pipeline takes, and any component that has not been ported is simply not available. The Python Dash is the reference implementation and the Julia one follows it, which is the right way round for maintenance and the wrong way round if you need a component today.
The second is a team that needs a production deployment with a supported release. The newest tag is v1.5.0 from January 2024, the default branch is dev, and the project is maintained by the community with a banner pointing to the Plotly Community rather than to Plotly itself. The README does invite sponsorship and consulting for those who want to accelerate the work, which tells you what the answer is for a team with a deadline: you pay for it or you do it yourself.
The third is a team that wants interactive plots in a notebook rather than an application. Dash is for applications, with a server, callbacks and a React frontend. If the requirement is a figure in a Jupyter notebook that updates when a parameter changes, that is a different problem with a different answer, and Dash.jl does not solve it.
The alternative worth comparing is the Python Dash itself, run against a Julia service over HTTP, and the difference in approach is instructive. A Julia service that exposes a REST endpoint, with the Python Dash talking to it, gives you the full component library and the mature Plotly ecosystem immediately, and the cost is a network hop on every callback and two languages in the stack. Dash.jl removes the hop and the second language, and the cost is the component lag, the older release line and the fact that the Python original is where new Dash features land first.
For a team whose analysis is in Julia and whose users only need a chart, a much smaller tool fits. Plots.jl, the Julia plotting library that predates the Dash port and has no web application layer at all, covers the case where the deliverable is a figure or a static report rather than an app with dropdowns and callbacks.
Editorial conclusion
Dash.jl fits a Julia team that wants a dashboard without writing JavaScript and without leaving the Julia process for the analysis, and that is willing to accept the port's rough edges. It does not fit a team that needs the full Dash component library, since the components are generated alongside the Python and R ones and lag behind, and it does not fit a production service that needs a maintained release cadence, since the newest tagged version is v1.5.0 from 2024-01-05. Before you adopt it, check the Dash for Julia user guide for the component coverage you need and install from the dev branch, which is where the work is happening.
Frequently asked questions
What is Dash.jl?
It is a Julia interface to the Plotly Dash ecosystem for creating analytic web applications in Julia, with no JavaScript required. It is built on top of Plotly.js, React and HTTP.jl, so the browser still runs a React frontend while the analysis stays in Julia.
How do I install Dash.jl?
Run pkg> add Dash for the most recently released version, or pkg> add Dash#dev for the latest stable development version. The repository's default branch is dev, and the newest tagged release is v1.5.0 from 2024-01-05, so the two channels differ considerably.
How do I write a callback in Dash.jl?
Register it with the callback! function, passing Output, Input and State objects, and use a do block for the function body. The callback function must have the signature (inputs..., states...) and return a value with the same number of elements as the number of Outputs it updates.
How does Dash.jl name components compared with Python Dash?
The dotted path becomes a single lowercase name with the parts run together: dash.html.Div is html_div, dash.dcc.Graph is dcc_graph, and dash.dash_table.DataTable is dash_datatable. Component functions take the same keyword arguments as in Python, with an additional signature that accepts a children maker function, which is what the do syntax uses.
What is the maintenance status of Dash.jl?
The README says Julia components can be generated in tandem with the Python and R components, and the repository carries a banner stating it is maintained by the Plotly Community. The last push to the repository was on 2026-06-04, on the dev branch, while the most recent release is v1.5.0 from 2024-01-05.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/plotly-dash-jl)Was this useful?