---
name: datatailr-deploy-app
description: Deploy a web app on the Datatailr platform using the Python SDK. Supports Streamlit, Dash, Flask, FastAPI, Panel, and standalone Notebook (Voila) apps. Use when the user asks to create and deploy an app, dashboard, web app, or notebook app on Datatailr / dt.
---

# Deploy an App on Datatailr

## Overview

Datatailr deploys apps as containerized jobs. You write a standard web app using any supported framework, then use the `datatailr` Python SDK to deploy it. The SDK handles packaging, image building, and scheduling. The SDK is already installed in the workspace -- do not look for it.

## Project layout

The deploy script must live **outside** the app module directory; it is only used locally to register and run the app. Do not use hyphens in directory names -- use underscores. Always prefer **absolute imports** (`from my_app.utils import ...`) instead of relative imports (`from .utils import ...`).

**Only the app package directory** (e.g. `my_app/`) is packaged and sent to the remote. Root-level files such as `deploy.py`, a root `setup.py`, or root `requirements.txt` are not included. Therefore **all files required for the job** (app code, `setup.py`, `pyproject.toml`, Cython sources, data files, etc.) must live **inside** the app package directory. For installable packages (e.g. with Cython), put `setup.py` and any build assets inside that directory.

```
my_project/
├── my_app/
│   ├── __init__.py
│   ├── app.py        # App code
│   └── setup.py      # If needed; must be inside my_app/
└── deploy.py         # Deploy script (outside my_app/; not sent to remote)
```

## Deploy script pattern

The entrypoint import and what the module must expose differ by framework — see the framework-specific file for the exact deploy script pattern.

Key parameters:
- `name`: human-readable name for the app on the platform.
- `entrypoint`: see the framework-specific file for what to import and pass.
- `framework`: one of `"streamlit"`, `"dash"`, `"flask"`, `"fastapi"`, `"panel"`.
- `resources`: CPU and memory for the container. Defaults to 128MB / 0.25 CPU.
- `python_requirements`: a list of pip package names (e.g. `["streamlit", "cython"]`) or a path to a `requirements.txt` file. The path is resolved **locally** when the job definition is built (at deploy time); the file is read on the machine running the deploy script and its **contents** are sent to the remote. If using a path, the file must exist where you run `python deploy.py` (e.g. `my_app/requirements.txt` when running from project root). Must include the framework itself.
- `app.run()` saves the definition AND starts the app. Use `app.save()` to only save.
- `python_version`: Python version for the container image (default `"auto"` -- auto-detects from your environment).
- `build_script_pre` / `build_script_post`: shell commands for the Docker image build. If the user needs to install OS packages or system libraries, see [datatailr-build-scripts](../datatailr-build-scripts/SKILL.md) for formatting details. If the script must operate on the installed package (e.g. run Cython or post-install steps), the package is installed at `/opt/datatailr/usr/lib/python/site-packages/<package_name>` where `<package_name>` is the **name of the directory that is deployed** (e.g. `my_app`); use that path in the script.
- `env_vars`: dict of environment variables passed to the running container.
- `run_as` / `acl`: leave unset to use default permissions. Only if the user explicitly requests access restrictions, see [datatailr-acl.md](../datatailr-acl.md). If their request is vague (e.g., "restrict access"), ask who should be able to see, edit, and operate the job before proceeding.

## Framework-specific details

Read **only** the file for the framework being deployed:

- Streamlit: see [streamlit.md](streamlit.md)
- Dash: see [dash.md](dash.md)
- Flask: see [flask.md](flask.md)
- FastAPI: see [fastapi.md](fastapi.md)
- Panel: see [panel.md](panel.md)
- Voila (notebook apps): see [voila.md](voila.md)
- Jupyter (notebook apps): see [jupyter.md](jupyter.md)

## Build environment and native dependencies

Datatailr jobs run in **Linux (Debian) containers**. The user's local OS (macOS, Windows, etc.) is **irrelevant** to the build.

**If the app uses Cython, C extensions, native libraries, or any dependency that requires a compiler or system headers, you MUST read [datatailr-build-scripts](../datatailr-build-scripts/SKILL.md) before writing the deploy script.** The build image is minimal and has no compiler or build tools — they must be installed explicitly via `build_script_pre`. Do not assume they are present and do not skip them based on a deploy command succeeding (it may have used cached layers).

## Deploying

After creating all the files, tell the user to activate their venv (if using one) and run the deploy script; if possible, give them the exact command to run. Do not mention `PATH`, `PYTHONPATH`, venv bin paths, or any internal details. Do not print the full app code at the end.
When you (the agent) run the deploy script yourself, you may get `RuntimeError: Datatailr CLI ('dt') is not available.` or an `ImportError` for `datatailr`. If user is using a venv (ask if they are), you need to invoke the deploy script as `PATH="/path/to/.venv/bin:$PATH" .venv/bin/python deploy_script.py` so that `dt` is on `PATH`. If `dt` is also not installed in the venv, tell the user to run `datatailr setup-cli`. Do not run `setup-cli` yourself as it's an interactive command which requires input from the user.

## Checklist

- [ ] App code follows the framework-specific pattern (see the framework file)
- [ ] Deploy script is outside the app module directory
- [ ] `entrypoint` and module requirements follow the framework-specific pattern (see the framework file)
- [ ] All files required for the job (including setup.py, Cython sources, etc.) are inside the app package directory
- [ ] `framework` is explicitly set
- [ ] `python_requirements` includes the framework and all dependencies
- [ ] If native code / Cython / system libraries are needed: read [datatailr-build-scripts](../datatailr-build-scripts/SKILL.md) and set `build_script_pre` / `build_script_post`
- [ ] No hyphens in directory names (use underscores)

## Platform environment variables

The platform sets these environment variables in every running app container. Use them when the app needs to know its runtime context:

- `DATATAILR_JOB_NAME`: name of the running job.
- `DATATAILR_USER`: username running the job.
- `DATATAILR_JOB_TYPE`: always `app` for apps.
- `DATATAILR_JOB_ENVIRONMENT`: Datatailr compute environment for this job (`dev`, `pre`, or `prod`).
- `DATATAILR_DOMAIN`: platform domain (useful for constructing URLs).

Dash apps also get `DASH_REQUESTS_PATHNAME_PREFIX` for URL routing (see [dash.md](dash.md)).

## Calling other services

If the app needs to fetch data from a Datatailr service, see [service-communication.md](../service-communication.md) for how to construct the internal URL and authenticate.
