Skip to content
Back to skills

Domino Apps

ASecurity

Publish, deploy, update, restart, stop or roll back a web application as a Domino App, and automate those steps over the Apps API or a CI/CD pipeline. Use whenever the user wants to publish, deploy, ship, launch, release or host an app (React/Vite, Streamlit, Dash, Flask, Shiny, Gradio, FastAPI, Rust) on Domino, make an existing app work behind Domino's reverse proxy (app.sh entry point, mandatory 0.0.0.0:8888, DOMINO_RUN_HOST_PATH, relative base, HashRouter, server-side model endpoint calls)...

  • 3 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 10, 2026
ai-agentspythonrustreactnodeexpressfastapiflaskgitapidatabase

Works with

  • cli
  • api

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 6 files and shows the line behind each finding

Scanned November 10, 2026

npx -y skills add dominodatalab/domino-ai-plugin --skill domino-apps --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Domino Apps?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Domino Apps
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/dominodatalab-domino-apps/badge)](https://www.skillsdirectory.com/skills/dominodatalab-domino-apps)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: domino-apps
description: Publish, deploy, update, restart, stop or roll back a web application as a Domino App, and automate those steps over the Apps API or a CI/CD pipeline. Use whenever the user wants to publish, deploy, ship, launch, release or host an app (React/Vite, Streamlit, Dash, Flask, Shiny, Gradio, FastAPI, Rust) on Domino, make an existing app work behind Domino's reverse proxy (app.sh entry point, mandatory 0.0.0.0:8888, DOMINO_RUN_HOST_PATH, relative base, HashRouter, server-side model endpoint calls), create a new App version, deploy an older version, start or stop an App over /api/apps/v1, or set up GitHub Actions deployment to Domino. Not for scaffolding a brand-new app from scratch (domino-app-init) or for diagnosing 404s, blank pages or broken routing in an already published app (domino-debug-proxy); use it when those hand off to publishing.
compatibility: Domino 6.3 and Domino Cloud. Requires DOMINO_API_HOST; in a run use DOMINO_API_PROXY, outside a run a Personal Access Token or service account token.
---

# Domino Apps

Applies to Domino 6.3 and Domino Cloud.

A Domino App runs project code in a container behind Domino's reverse proxy. The proxy authenticates every request, strips the App's URL prefix, and forwards the viewer's token as `Authorization: Bearer` (secure identity propagation, the default).

## Rules every App must satisfy

1. **Make the App idempotent.** It restarts at any time and can run as several replicas at once: startup changes nothing (migrate and seed in a Job before publishing), each write is an upsert or carries an idempotency key under a unique constraint, so a retry stores it once, and state lives in a Dataset or database, not in memory or on the App's disk ([details](./FRAMEWORKS.md#make-the-app-idempotent)).
2. **Serve on `0.0.0.0:8888`.** An App that does not expose a server on that address and port fails to start. Port 8888 is mandatory, not a default.
3. **The entry point is a launch file** in the project (`app.sh`, or a Python or R script). It is fixed for the life of the App; create a new App to change it.
4. **Read the URL prefix from `DOMINO_RUN_HOST_PATH`** wherever a framework needs its base path (Dash `requests_pathname_prefix`, Gradio `root_path`). Never assemble it from the project owner, name and run ID; the prefix is not derived from them.
5. **Use relative URLs** for assets and API calls (Vite `base: './'`, `new URL('api/', document.baseURI)`), never root-absolute `/assets/...` or `fetch('/api/...')`. They break when the App URL lacks its trailing slash; add it ([details](./FRAMEWORKS.md#behind-dominos-app-proxy)).
6. **Keep secrets on the server.** Model endpoint tokens live in project or user environment variables and are read by backend code. Anything in a `VITE_`-prefixed variable is compiled into the browser bundle.

## Quick start

| Framework | `app.sh` runs | Details |
|---|---|---|
| Vite + React | `node server.js` serving a build made once by `scripts/build-dist.sh`; never installs or builds | [REACT-VITE-GUIDE.md](./REACT-VITE-GUIDE.md) |
| Streamlit | `streamlit run app.py --server.port 8888 --server.address 0.0.0.0 --server.enableCORS false --server.enableXsrfProtection false` | [FRAMEWORKS.md](./FRAMEWORKS.md) |
| Dash | `python app.py` with `Dash(__name__, routes_pathname_prefix='/', requests_pathname_prefix=os.environ.get('DOMINO_RUN_HOST_PATH'))` and `app.run(host='0.0.0.0', port=8888)` | [FRAMEWORKS.md](./FRAMEWORKS.md) |
| Flask | `python -m flask run --host=0.0.0.0 --port=8888` or `gunicorn -w 4 -b 0.0.0.0:8888 app:app` | [FRAMEWORKS.md](./FRAMEWORKS.md) |
| Shiny | `R -e 'shiny::runApp("./", port=8888, host="0.0.0.0")'` | [FRAMEWORKS.md](./FRAMEWORKS.md) |
| Rust (axum) | the prebuilt binary; never compiles | [domino-rust-apps](../domino-rust-apps/SKILL.md) |

Vite: `base: './'` and `HashRouter`; `BrowserRouter` breaks nested routes.

## Lifecycle

Create, publish and deploy are separate steps. Publishing records an immutable version (code commit, environment revision, mounts, identity propagation); deploying starts it. Hardware tier, autoscaling, vanity URL and iframe settings are deployment settings: changing them restarts the instance without creating a version. Develop in a workspace with **App Preview** (a real App runtime, author-only at `/preview/<draftAppId>`), then **Publish App**, then **Deploy** the version from the App details page.

Check three things before publishing. **Builds**: Vite and Rust Apps start a build made once in a Workspace or Job, named by date, with the previous build kept and the label in Version Notes ([details](./FRAMEWORKS.md#build-once-and-version-builds)). **Files**: the App runs the project's committed files, so sync first (DFS Workspace: **File Changes > Sync to Domino**; Git-based: commit and push) or the start fails with `entry script 'app.sh' not found`. **Packages**: the App uses the project's Compute Environment, not what you `pip install` in a Workspace (`streamlit: not found`, exit 127); check with `python -c "import <framework>"` and fix it as [FRAMEWORKS.md](./FRAMEWORKS.md#dependencies) shows.

## Environment variables and headers

Injected at start: `DOMINO_RUN_HOST_PATH` (URL prefix, trailing `/`), the `DOMINO_PROJECT_*` and `DOMINO_RUN_ID` identifiers, `DOMINO_STARTING_USERNAME` (who started the run, not the viewer), `DOMINO_API_HOST` and `DOMINO_API_PROXY` (in-cluster API addresses; never in browser links), plus project and user environment variables ([full list](./FRAMEWORKS.md#environment-variables)). The viewer is the token's `preferred_username` claim; read `domino-username` only when no token arrives (Apps with extended identity propagation never get it, and there a client can send its own).

## Calling Domino APIs and model endpoints from an App

- **As the publisher** (the user who started the App): `$DOMINO_API_PROXY/api/...` with no `Authorization` header; code that needs a bearer gets one per request from `$DOMINO_API_PROXY/access-token`.
- **As the viewer**: the request's bearer token on `$DOMINO_API_HOST`. Without extended identity propagation (published by a SysAdmin or CloudAdmin; viewer consent) most routes reject it, often with 500 ([details](./FRAMEWORKS.md#viewer-identity-and-domino-api-calls)). No token: return 401, since `$DOMINO_API_HOST` runs calls without `Authorization` as the publisher.
- **Model endpoints**: from backend code only, with `MODEL_API_URL` and `MODEL_API_TOKEN` from Project environment variables; HTTP Basic with the token as username and password for synchronous endpoints, a bearer for asynchronous ones ([details](./FRAMEWORKS.md#calling-a-model-endpoint-from-any-framework)).

Auth: https://docs.domino.ai/cloud/reference/api/domino-api-authentication ; legacy API keys (`X-Domino-Api-Key`) are deprecated.

## REST automation

`/api/apps/v1` for create, versions, publish (drafts), start and stop; `/api/apps/beta` only for instance reads (list instances, logs, real-time logs, views). Full chain, bodies and the logs route: [API-APPS.md](./API-APPS.md). CI/CD with GitHub Actions and a service account: [REACT-CICD.md](./REACT-CICD.md).

## Reference files

- [REACT-VITE-GUIDE.md](./REACT-VITE-GUIDE.md): Vite config, Express backend, HashRouter, App Preview
- [REACT-CICD.md](./REACT-CICD.md): GitHub Actions workflow and Public API deploy script
- [FRAMEWORKS.md](./FRAMEWORKS.md): Streamlit, Dash, Flask, Gradio, FastAPI, Shiny, dependencies, viewer identity, proxy behaviour and limits
- [API-APPS.md](./API-APPS.md): v1 vs beta routes, publish chain, logs
- [TROUBLESHOOTING.md](./TROUBLESHOOTING.md): symptoms, causes and fixes

Docs: https://docs.domino.ai/cloud/platform-capabilities/core-concepts/apps (same under `/6.3/`). Related skills: `domino-app-init` (scaffold), `domino-debug-proxy` (diagnose), `domino-api-intro` (auth, hosts), `domino-ui-bootstrap` (design system SPA), `domino-extensions` (mount an App in the Domino UI).

Files in this skill

  • API-APPS.md11.3 KB
  • FRAMEWORKS.md25.2 KB
  • REACT-CICD.md12.7 KB
  • REACT-VITE-GUIDE.md9.1 KB
  • SKILL.md7.8 KB
  • TROUBLESHOOTING.md11.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in ai-agents →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.