Skip to content

Usage Patterns

Fast Dash helps build and deploy Proof of Concept (POC) applications lightning fast while having you, the innovator, write as less UI development code as possible.

This document outlines some common Fast Dash patterns and how you can use these ideas to fastrack your deployment.

Before you begin

Never worry about web app development or deployment before you are comfortable about your main Python functionality and supporting code.

Note

The whole Fast Dash promise is to decrease the time needed for app development after you have written the main Python software, not distracting you from your innovation.

So focus on the main functionality of your code and don't worry about the web app.

After you are comfortable with your Python function ...

1. Setting input components

By setting the correct callback function type hints, their default values, or choosing Dash components, and built-in Fast components, you can display most common UI elements for users to enter their inputs.

Note

If you used the proper Python function type hinting practices, you might not have to make many changes to your code.

Here are some examples:

Input is Type hint Default value Example
Text
Text str Any def my_func(arg1: str)
Single item from a list of fixed items str List of allowed text items def get_gdp(country: str = ["USA", "Canada", "Mexico"])
List of items and users can add their own items list Blank def enter_web_urls(urls: list)
List of items and users must choose from a fixed set of items list List of fixed set of items def enter_web_urls(urls: list = ["google.com", "youtube.com", "facebook.com", "bing.com"])
Numbers
Number int or float Blank def enter_score(score: int) or def enter_score(score: float)
Bounded number int or float List of bounds and step size in the format: range(min, max, step) def enter_score(score: int = range(0, 10)) or def enter_score(score: float = list(np.arange(0, 10, 0.1)))
Images and documents
Image PIL.Image.Image Blank or default image (PIL format) def upload_image(image: PIL.Image.Image)
Any document Built-in component Upload Blank def upload_doc(doc: Upload)
Dates
Single date datetime.date or datetime.datetime Blank or default date def set_date(date: datetime.date = datetime.date(2023, 1, 1))
Modern type hints
Fixed set of string options Literal["a", "b", "c"] Any of the values def pick(choice: Literal["red", "green", "blue"])
Enum members enum.Enum subclass Any enum member class Color(Enum): RED = "red"
def pick(c: Color)
Bounded number via type hint Annotated[int, range(min, max, step)] Any int/float def score(s: Annotated[int, range(0, 100)])
Dropdown via type hint Annotated[str, [list]] Any of the values def pick(c: Annotated[str, ["USA", "Canada"]])
Optional value Optional[T] Any T def ping(text: Optional[str])
Reactive inputs
Cascading dropdown Use depends_on(parent, resolver) as the default The parent input's name and a resolver that returns options def pick(country: str = ["USA"], state: str = depends_on("country", lambda c: states[c]))

2. Setting output components

We've seen that we can set the desired input component by choosing a specific combination of input type hints and default values. Setting output components works similar to that.

Reminder

Return type hints in Python are written in the function description following the -> symbol.

For example,

  • def my_func(...) -> str indicates that the first return value is a string.
  • def my_func(...) -> (str, int) indicates that the first return value is a string and the second return value is an integer.

Here's how to set the desired components using return type hints:

Output is Type hint Example
Text str def my_func(...) -> str:
Number (treated as text) int or float def my_func(...) -> int: or def my_func(...) -> float:
Image PIL.Image.Image def my_func(...) -> PIL.Image.Image:
Matplotlib figure plt.Figure def my_func(...) -> plt.Figure:
Plotly graph Built-in component Graph def my_func(...) -> Graph:
Pandas Dataframe pd.DataFrame or built-in component Table. Using Table lets you set the pagination page size using Table(page_size=20) def my_func(...) -> pd.DataFrame: or def my_func(...) -> Table: or def my_func(...) -> Table(page_size=20):
Conversation (chat) Built-in component Chat. Output must be formatted as a dictionary in the format {"query": query, "response": response} def my_func(...) -> Chat:

3. Arranging output components

Fast Dash allows customizing the visual arrangement of your output components. The idea is using “mosaics.” Drawing inspiration from Matplotlib’s subplot_mosaic method, Fast Dash lets you craft layouts using an ASCII-esque diagram or a string list.

Each unique letter or string in this mosaic signifies a unique component. This approach is a game-changer, especially when you’re aiming for non-uniform grid layouts.

For example, imagine the output arrangement you want is something like in the following image:

Example mosaic layout

In this case, you can define your mosaic to be “ABB \n CDE”. Fast Dash will set the app for five outputs and divide the space into six equally-sized boxes placed as a 2 x 3 grid.

The first output gets the top-left box. The second output stretches across the next two boxes in the top row. And each of the remaining three outputs gets its own box in the row below.

Refer to the examples below to understand this idea better.

Example 1: Two outputs

We have two outputs and we want them to appear one below the other.

mosaic = """
A
B
"""

@fastdash(mosaic=mosaic)
def my_func(arg1: str) -> (str, str):
    return "A", "B"

Output:

Example 1

Example 2: Three outputs

We have three outputs. The first two should appear next to each other in the first row and the third should appear below them taking up the entire second row.

mosaic = """
AB
CC
"""

@fastdash(mosaic=mosaic)
def my_func(arg1: str) -> (str, str, str):
    return "A", "B", "C"

Output:

Example 2

Example 3: Four outputs

We have four outputs. The first two should appear one below the other in the first column, and the remaining two should take up the entire second and third columns respectively.

mosaic = """
ACD
BCD
"""

@fastdash(mosaic=mosaic)
def my_func(arg1: str) -> (str, str, str, str):
    return "A", "B", "C", "D"

Output:

Example 3

Example 4: Five outputs

This example has five outputs. Here are the requirements:

  • The 1st output must appear first.
  • The 2nd output must be twice as wide as the first output.
  • The 3rd, 4th and 5th outputs must be in the second row and have the same width.
mosaic = """
ABB
CDE
"""

@fastdash(mosaic=mosaic)
def my_func(arg1: str) -> (str, str, str, str, str):
    return "A", "B", "C", "D", "E"

Output:

Example 4

Example 5: Eight outputs

This is a slightly complicated example with 8 outputs, reminiscent of some BI dashboards. Here's what we want:

  • The first 4 components appear one after the other horizontally (like overview KPIs in a dashboard).
  • The 5th output appears directly below the first 3 components while the 6th appears directly below the 4th.
  • The 7th appears directly below 5th and the 8th appears directly below the 6th.
  • Let's add a complication intentionally: Components 5 through 8 should be twice as tall (vertically) as the first 4 components.

No problem! it's easy to have this layout with Fast Dash just by writing the appropriate mosaic string, without touching the main Python code.

# Notice that the second and third component rows have been repeated 
# to make them appear twice as high as the first component row
mosaic = """
ABCD
EEEF
EEEF
GGGH
GGGH
"""

@fastdash(mosaic=mosaic)
def my_func(arg1: str) -> (str, str, str, str, str, str, str, str):
    return "A", "B", "C", "D", "E", "F", "G", "H"

Output:

Example 5

4. Multi-function tabbed apps

When you have several related functions and want them in one app, pass a list of callbacks. Fast Dash builds a tabbed layout where each function gets its own tab with independent inputs, outputs, and callbacks.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from fast_dash import FastDash

def greet(name: str) -> str:
    return f"Hello, {name}!"

def add(a: int, b: int) -> int:
    return a + b

app = FastDash([greet, add], tab_titles=["Greeter", "Adder"])
app.run()

tab_titles is optional — without it, tabs are named after the functions (converted from snake_case to Title Case). The navbar, about modal, and streaming notifications are shared across all tabs; component IDs are namespaced per tab so they don't collide.

5. Reactive inputs with depends_on

When one input's options should depend on another input's value (cascading dropdowns, dynamic ranges, prefilled values), use depends_on as the dependent parameter's default:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from fast_dash import fastdash, depends_on

countries = {
    "USA": ["California", "Texas", "New York"],
    "India": ["Maharashtra", "Karnataka", "Delhi"],
}

@fastdash
def pick_state(
    country: str = list(countries),
    state: str = depends_on("country", lambda c: countries[c]),
) -> str:
    return f"{state}, {country}"

The first argument to depends_on is the parameter name of the parent input. The second is a resolver function that receives the parent's current value and returns one of:

  • a list — sets the dependent dropdown's options and clears its value;
  • a dict like {"data": [...], "value": ...} — sets either or both;
  • a scalar — sets just the dependent's value (e.g. derived numbers, prefilled text).

If the resolver raises an exception, no update fires. Chains work: A → B → C is just two depends_on declarations.

6. Multi-step pipelines

When your workflow naturally splits into stages — load data → transform → visualize — turn the whole pipeline into a single app with steps=:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from fast_dash import FastDash, from_step
import pandas as pd

def load_data(rows: int = 100) -> pd.DataFrame:
    """Load a sample dataset."""
    return pd.DataFrame({"x": range(rows), "y": [i * 2 for i in range(rows)]})

def double(data=from_step(load_data)) -> pd.DataFrame:
    """Double every value."""
    return data * 2

def summarise(data=from_step(double), prefix: str = "Result:") -> str:
    """One-line summary."""
    return f"{prefix} {len(data)} rows, sum={data.values.sum()}"

FastDash(steps=[load_data, double, summarise], title="Pipeline Demo").run()

Each step is rendered as a dedicated panel with its own inputs and outputs. A stepper progress indicator at the top of the main area shows the current step. Click Run to execute the active step, then Next to advance.

Wiring upstream outputs into downstream inputs

Use from_step(prev_fn) as a parameter default to pull a previous step's return value into the current step's parameter:

  • The framework caches each step's return value per browser session.
  • When a downstream step runs, from_step parameters are filled in automatically — no UI is rendered for them.
  • Mix from_step parameters with regular UI parameters freely (see summarise's prefix above).
  • from_step(prev_fn, transform=lambda x: ...) applies a function to the cached value before passing it.
  • Back rewinds one step and clears all downstream cached results, so you can rerun a different branch of inputs.
  • Run executes the currently visible step. Until you click Run, the Next button is disabled.
  • Trying to run a downstream step before its from_step source has been run produces a friendly error message instead of a traceback.
  • State is keyed by a UUID stored in the browser's session storage, so opening the app in a new tab gives you a fresh pipeline.

Limits

  • Linear pipelines only — no conditional branching in this release.
  • The cache lives in the FastDash process; a server restart or a multi-worker deployment loses session state. Acceptable for prototyping.

7. Selecting other configurations

Finally, customize your app by controlling various options like the theme of the app, social media branding links, subheaders, deployment mode and so on.

In the next section, we'll see what Fast Components are, what separates them from other Dash components, and how we can easily modify Dash components to make them compatible with Fast Dash.