> ## Documentation Index
> Fetch the complete documentation index at: https://docs.domino.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Develop and test Apps

> Develop a Domino App in a Workspace, run it in App Preview, iterate with live sync, and reopen a published App in a Workspace to change it safely.

Write the App in a [Workspace](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/workspaces) and run it with **App Preview**. Preview runs your committed code in a real App runtime that only you can reach, with the App's authentication, networking, URL path, mounts, and environment variables. A Workspace terminal has none of those, so Preview is where you find out whether the App works as an App.

The steps use the **Synthetic Transaction Review** App from [Get started](https://docs.domino.ai/6.3/platform-overview/getting-started-with-domino.md). They are the same for any App in any [framework](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/develop-and-test/app-frameworks.md).

## Before you begin

* A Git-based Project you can edit. Only Git-based Projects support [Edit in Workspace](#update-an-app-viewers-already-use).
* A Compute Environment with your framework installed. The transaction review App needs `dash` and `dash-mantine-components`.
* For the transaction review App, the `AML` Dataset and the `MODEL_ENDPOINT_URL` and `MODEL_ACCESS_TOKEN` Project environment variables from Get started.

## 1. Start a Workspace for the App

On the Project's **Deploy** > **Apps & Agents** page, select **Create**, then **App in Workspace**. Domino starts a Workspace with the Project's code. Any Workspace in the Project works the same way.

> [!NOTE]
>
> Creating an App doesn't deploy it. Viewers see nothing until you deploy a version. Before Domino 6.3.0, **Publish App** created and deployed the App in one step. If your administrator turns off the [`EnableAppsSDLC` feature flag](https://docs.domino.ai/6.3/admin/configuration/feature-flags), which is on by default in 6.3.0, that legacy flow still applies.

## 2. Write the entry point

An App is application code plus an entry point that starts a web server. The server must listen on `0.0.0.0`, port `8888`. Domino routes viewers to that port. An App that listens anywhere else fails to start.

The transaction review App's entry point is `app.sh`. The address and port are set in `app.py`:

```bash app.sh theme={null}
#!/usr/bin/env bash
set -euo pipefail

python app.py
```

```python app.py (excerpt) theme={null}
def domino_path_prefix() -> str:
    prefix = os.environ.get("DOMINO_RUN_HOST_PATH", "/")
    return f"/{prefix.strip('/')}/" if prefix.strip("/") else "/"


app = Dash(
    __name__,
    title="Synthetic Transaction Review",
    routes_pathname_prefix="/",
    requests_pathname_prefix=domino_path_prefix(),
)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8888, debug=False)
```

Two other things in this code apply to every App. Domino serves each App under its own URL path and puts that path in `DOMINO_RUN_HOST_PATH` at startup. Dash, Streamlit, Flask, and any other framework that takes a base path must read it from that variable. A path assembled from the Project name or run ID stops working after a restart; see [Migrate an App that builds its own path](#migrate-an-app-that-builds-its-own-path). The endpoint URL and token come from Project [environment variables](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/compute-environments/manage-compute-environments/manage-environment-variables), not from the code.

[App frameworks](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/develop-and-test/app-frameworks.md) has the launch line for Streamlit, Flask, Shiny, and static HTML. A [coding assistant with Domino Skills](#build-with-coding-assistants-and-domino-skills) can scaffold an App that already follows these rules.

## 3. Commit your changes

Commit `app.py` and `app.sh`. Preview runs the latest commit. Uncommitted edits never reach it.

## 4. Run the App in App Preview

In the Workspace's **App Preview** tab, set the App file to `app.sh`, keep the `AML` Dataset mounted, and start the preview. These settings become the defaults when you publish, so the version you publish matches what you tested.

Domino creates a **Draft App** for this Workspace and starts it in a private App runtime. The first load takes about as long as starting a deployed App. When the page loads, select **Review** next to a transaction. A score confirms that the App reached the Dataset and the endpoint.

![App Preview settings beside the Synthetic Transaction Review App with a scored transaction.](https://mintcdn.com/dominodatalab-e871cec4/tAN89q5OuNV-ii4x/images/getting-started/synthetic-transaction-review-preview.png?fit=max\&auto=format\&n=tAN89q5OuNV-ii4x\&q=85\&s=6af7b928dbfa16090269db97986bea55)

> [!WARNING]
>
> **Preview runs as you, against real Domino resources.** If the Draft App starts a Job or writes to a Dataset, that happens for real. Point writes at test data and destinations while you develop.

## 5. Iterate with live sync

Edit the code and commit. For example, change `head(20)` to `head(50)` in `review_queue()` to show 50 transactions. Live sync applies the new commit to the running preview without a full restart. A preference controls whether it syncs on every commit or only when you ask.

While the preview runs, you can also:

* Add query parameters to test parameterized views.
* Open the preview in its own tab at `/preview/<draftAppId>`. The URL works only for you.
* Read the App logs or change preview settings from the Workspace sidebar.

## 6. Publish

Select **Publish App** in the Workspace. Domino records a version from the preview settings. The Draft App and the Workspace stay as they are. Continue with [Publish](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/publish.md).

## Draft lifecycle

A Draft App survives Workspace restarts.

* Stopping the Workspace stops the preview. Administrators can also stop previews.
* Deleting the Workspace deletes the Draft App.
* Each Draft App has one preview at a time. Starting a new preview stops the old one.
* Previews don't count against the per-Project limit on running Apps.
* Autoscaling applies to deployed versions. Test it after you deploy.

## Update an App viewers already use

**Edit in Workspace** opens a published version in a Workspace with its own Draft App. Viewers keep using the deployed version while you work. Nothing changes for them until you deploy the new version.

**1. Open the version in a Workspace**

On the App's details page, select the version and then **Edit in Workspace**. Domino creates a Workspace and a Draft App with that version's configuration and starts a preview.

**2. Change and test the code**

Edit and commit. Live sync applies each commit to the preview.

**3. Publish a new version**

Select **Publish App** and publish a new version of the same App. The entry point must match the App's. See [Publish](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/publish.md).

**4. Deploy it**

[Deploy](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/deploy.md) the version. If it misbehaves, [start the previous version](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/operate.md#roll-back-to-a-previous-version).

**Edit in Workspace** works in Git-based Projects. From a Domino File System (DFS) Project, [publish from a file](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/publish.md#publish-from-a-file-without-a-workspace).

To separate development from production, use a Git branch per environment and preview the branch before you publish it. Pair each branch with its own Compute Environment. Clone an environment instead of editing one that a published version uses, and name revisions for what changed, such as `v1.2-data-upgrade`.

## Build with coding assistants and Domino Skills

[Coding assistants](https://docs.domino.ai/6.3/platform-capabilities/features/coding-assistants) run in your Workspace. [Domino Skills](https://docs.domino.ai/6.3/platform-capabilities/features/coding-assistants/domino-skills.md) add App-specific actions:

| Skill | Use it to |
| :- | :- |
| **domino-app-init** | Scaffold a Domino-ready web App in React, Streamlit, Dash, or Flask. |
| **domino-rust-apps** | Build a Rust web App with axum and publish a prebuilt binary that starts without compiling. |
| **domino-ui-design** | Build an App that matches the Domino Design System. |
| **domino-debug-proxy** | Debug Domino proxy and routing problems. |
| **app-deployment** | Deploy a web App to Domino. |
| **domino-trace-setup** | Set up tracing for an Agent or large language model (LLM) application. |

Ask the assistant to "create a Streamlit app for this project" and it uses **domino-app-init**. The [skills reference](https://docs.domino.ai/6.3/reference/skills.md) lists every skill.

## Migrate an App that builds its own path

With the `SecureIdentityPropagationToAppsEnabled` feature flag on, which is the default since Domino 6.3.0, Domino hosts Apps at `https://<domino-domain>/apps/<app-id>/`. An App that builds its path from `DOMINO_PROJECT_OWNER`, `DOMINO_PROJECT_NAME`, and `DOMINO_RUN_ID` keeps running until its next restart. Then it shows a blank page, a `404`, or a `502`, or a Dash App stops serving assets and callbacks.

Read the path from `DOMINO_RUN_HOST_PATH` instead. Domino sets it at startup, and it's correct whether or not the flag is on.

```python Before theme={null}
user    = os.environ.get("DOMINO_PROJECT_OWNER")
project = os.environ.get("DOMINO_PROJECT_NAME")
run_id  = os.environ.get("DOMINO_RUN_ID")
runurl  = f"/{user}/{project}/r/notebookSession/{run_id}/"

app = Dash(__name__, routes_pathname_prefix="/", requests_pathname_prefix=runurl)
```

```python After theme={null}
runurl = os.environ.get("DOMINO_RUN_HOST_PATH")

app = Dash(__name__, routes_pathname_prefix="/", requests_pathname_prefix=runurl)
```

Publish a new version, deploy it, and check that the page, callbacks, and assets load.

## Related

* [Publish](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/publish.md): Record a version of the Draft App.
* [Identity](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/identity.md): Read the viewer's identity in your code.
* [Run multiple Apps in a Workspace](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/workspaces/run-multiple-apps-in-a-workspace.md): Serve more than one App from one Workspace.


## Related topics

- [Apps](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/index.md)
- [App frameworks](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/develop-and-test/app-frameworks.md)
- [Operate Apps](https://docs.domino.ai/6.3/platform-capabilities/core-concepts/apps/operate.md)
- [Getting started with Domino: Build a transaction review App](https://docs.domino.ai/6.3/platform-overview/getting-started-with-domino/index.md)
