| name | fast-dash |
| description | Build a Fast Dash web app from a Python function. Use when the user wants to turn a function into an interactive app, add a UI to an existing function, or build a dashboard / form / wizard. Fast Dash infers UI components from type hints, so a well-typed function becomes an app with one decorator. |
Fast Dash
Fast Dash turns a Python function into a Plotly Dash web app. The @fastdash decorator reads the function's signature, maps each parameter's type hint to a UI component, maps the return type to an output component, and serves the result. No frontend, no callbacks, no boilerplate.
When to use this skill
Use this skill when the user:
- has a Python function and wants a UI for it ("make this a web app", "add a form", "dashboard around this")
- is prototyping an ML / data / API tool and wants shareable interactivity
- needs cascading inputs, a multi-step wizard, or multiple tools in one app
Do not use this for: production apps with complex routing, custom auth, or non-Python frontends — Fast Dash is opinionated for the single-file-Python-function use case.
Install
pip install fast-dash
The core pattern
from fast_dash import fastdash
@fastdash
def greet(name: str = "world") -> str:
return f"Hello, {name}!"
That is the whole app. Open the URL, type a name, click Run.
How to approach a Fast Dash task
- Start from the user's function. If they don't have one, write the smallest function that captures their intent.
- Add type hints and defaults. This is where the UI comes from —
int → number input, bool → checkbox, str with a list default → dropdown, etc. See references/components.md for the full table.
- Decorate with
@fastdash. For more control (tabbed multi-function apps, multi-step pipelines), use the FastDash(...) class directly.
- Run and verify. The decorator starts a server immediately on import. For notebooks, pass
mode="inline".
Common patterns
| Pattern | Syntax | When |
|---|
| Single function | @fastdash | One tool, one form |
| Multiple outputs | -> (Graph, Graph) + mosaic="AB" | Dashboard with several plots |
| Cascading inputs | state=depends_on("country", resolver) | Dependent dropdowns |
| Multiple tools, one app | FastDash([fn_a, fn_b], tab_titles=[...]) | Tabbed "apps" under one URL |
| Multi-step wizard | FastDash(steps=[fn_a, fn_b, fn_c]) + from_step(prev_fn) | Pipeline UX, one panel at a time |
| Streaming outputs | update("output_x", chunk) inside the fn + stream=True | LLM / token-by-token / progress |
| Notebook rendering | @fastdash(mode="inline") | Jupyter |
| Wrap a custom component | Fastify(dcc.Slider(...), "value") | Any Dash component |
Full examples for each: references/patterns.md.
Type hint → component quick reference
| Hint | Component |
|---|
str | Textarea |
int, float | Number input |
bool | Checkbox |
Literal["a", "b"] | Dropdown |
Annotated[int, range(0, 100)] | Slider |
list | Multi-select |
datetime.date | Date picker |
pd.DataFrame (return) | Table |
plotly.graph_objects.Figure (return) | Plotly chart |
PIL.Image.Image | Image upload / display |
Full table with every supported hint: references/components.md.
Built-in components to import
Pass these directly as inputs= or outputs= when you want to override inference:
from fast_dash import (
Text, TextArea, PasswordInput,
NumberInput, Slider,
Switch, MultiSelect,
DateInput, DateRange, ColorInput,
Upload, UploadImage,
Graph, Image, Table, Markdown, Chat, Download,
)
For streaming and building custom UIs, also available:
from fast_dash import (
Fastify,
depends_on,
from_step,
update, notify,
dcc, dbc, dmc, html,
)
Non-obvious things that will bite you
@fastdash starts the server on import. Put it in a if __name__ == "__main__": guard if the file is imported elsewhere, or skip the decorator and use FastDash(...).run().
- Default Bootswatch
theme= does not restyle Mantine chrome (v0.2.x). Only dark/light flips for known dark themes (CYBORG, DARKLY, SLATE, ...).
- Don't reuse a single component instance across inputs and outputs — pass the class (
inputs=Text) not an instance. Mutation surprises.
- Output labels come from the
return line of the source. REPL / exec contexts fall back to OUTPUT_1, OUTPUT_2. Pass output_labels=[...] to override.
Full list with reproducers: references/gotchas.md.
Decision tree
- User has one function, simple form →
@fastdash on the function, done.
- User has one function, multiple outputs →
@fastdash(mosaic="AB\nAC"), return a tuple of components.
- User has multiple independent tools →
FastDash([fn_a, fn_b], tab_titles=[...]).run().
- User has a pipeline (step 1 output feeds step 2) →
FastDash(steps=[fn_a, fn_b, ...]).run() with from_step(prev_fn) defaults.
- User has dependent dropdowns →
depends_on("parent_name", resolver) as a default value.
- User wants streaming / token-by-token output (LLMs, progress) → call
update(component_id, data) inside the function + stream=True on the app.
- User wants the app in a Jupyter notebook → add
mode="inline".
- User wants to not start the server immediately → use
FastDash(...) class, skip .run().
Before reporting complete
Run the app and verify it loads. If you can't open a browser:
- check the console for tracebacks
- confirm the port (default
8080) is free
- for notebooks, confirm
mode="inline" was set
If the user has dash[testing] installed, a headless smoke test is worthwhile. Otherwise, ask the user to verify the UI themselves.