domino-app-init ยท diff

git:20261001.b8e8054 to git:20261014.681e9c1

69 added, 68 removed. Audit A to A.

---
name: domino-app-init
- description: Scaffold a new Domino-ready web application (Vite + React, Streamlit, Dash, Flask, or Gradio) with proxy-compatible settings, port 8888 binding, and an app.sh entry point. Use when the user wants to start, initialize, or scaffold a new app to publish on Domino, or asks for a starter app.sh for a web framework.
+ description: Scaffold a new Domino-ready web application (Vite + React, Streamlit, Dash, Flask, Gradio or FastAPI) with the settings Domino's reverse proxy needs, the mandatory 0.0.0.0:8888 binding, DOMINO_RUN_HOST_PATH prefixes, server-side model endpoint calls, and an app.sh entry point. Use when the user wants to start, initialize, create or scaffold a new app to publish on Domino, or asks for a starter app.sh or starter app for a web framework on Domino.
+ compatibility: Domino 6.3 and Domino Cloud. Templates only; no API calls. Publishing the result needs a Domino project and a Compute Environment that contains the framework (and Node for Vite).
---
# Initialize a Domino App
+ Applies to Domino 6.3 and Domino Cloud.
+
Create a web application that works behind Domino's reverse proxy on the first publish.
## Inputs
Collect these before writing files. Skip any the user has already given.
- 1. **Framework**: `vite-react` (default), `streamlit`, `dash`, `flask`, or `gradio`.
- 2. **Project name**: name for the app folder and `package.json` (React only).
- 3. **Model API integration**: whether the app calls a Domino model endpoint, and if so its URL.
+ 1. **Framework**: `vite-react` (default), `streamlit`, `dash`, `flask`, `gradio` or `fastapi`.
+ 2. **Project name**: app folder name and `package.json` name (React only).
+ 3. **Model endpoint integration**: whether the app calls a Domino endpoint. If yes, the call goes through backend code and the user sets `MODEL_API_URL` and `MODEL_API_TOKEN` as Domino Project variables, never in the repository. The URL comes from the user; the token is the user's or one you create and store ([domino-apps/FRAMEWORKS.md](../domino-apps/FRAMEWORKS.md#calling-a-model-endpoint-from-any-framework)).
If the target directory already contains an app, stop and ask before overwriting anything.
## Steps
1. Copy the matching template from this skill's `assets/` folder into the project:
| Framework | Files to copy |
|---|---|
- | `vite-react` | `assets/vite-react/vite.config.js`, `assets/vite-react/app.sh`, `assets/vite-react/.env.example` |
- | `streamlit` | `assets/streamlit/app.sh` |
+ | `vite-react` | `assets/vite-react/vite.config.js`, `assets/vite-react/app.sh`, `assets/vite-react/server.js`, `assets/vite-react/.env.example` (run `npm create vite@latest` first if there is no Vite project yet, then `npm install express` and `npm install -D serve`) |
+ | `streamlit` | `assets/streamlit/app.sh`, and `assets/streamlit/app.py.template` saved as `app.py` |
| `dash` | `assets/dash/app.sh`, and `assets/dash/app.py.template` saved as `app.py` |
- | `flask`, `gradio` | No template; write the files from the snippets below |
+ | `flask`, `gradio`, `fastapi` | No template; write the files from the snippets below |
- 2. Make `app.sh` executable (`chmod +x app.sh`).
+ 2. Make `app.sh` executable (`chmod +x app.sh`) and commit the mode (`git update-index --chmod=+x app.sh`). The templates start with `cd "$(dirname "$0")"`, so `app.sh` works from the repo root or an app subfolder.
3. Keep these invariants in every generated file:
- - Bind to `0.0.0.0`, never `localhost` or `127.0.0.1`.
- - Listen on port `8888` unless the user asks for another port.
- - For Vite, set `base: './'` so assets resolve under the proxy prefix.
- 4. If the user wants Model API integration, add the endpoint URL and token as environment
- variables (see `.env.example`) and never hardcode credentials.
- 5. Finish with the post-initialization checklist below.
+ - Bind `0.0.0.0` on port `8888`. Domino requires both; an App on any other address or port fails to start.
+ - Where the framework needs its base path, read `DOMINO_RUN_HOST_PATH` (Dash `requests_pathname_prefix`, Gradio `root_path`). Never build the prefix from project owner, name and run ID.
+ - Use relative URLs for assets and API calls. For Vite set `base: './'` and use `HashRouter`.
+ - Secrets stay on the server: no token in a `VITE_` variable, no token in the repo.
+ 4. Add `.env`, `.env.local`, `node_modules/` and `dist/` to `.gitignore`; keep `.env.example`.
+ 5. **Check that the framework is in the Compute Environment.** The App runs in the project's environment (or the one chosen at publish time); packages `pip`-installed in a Workspace are not in it, and the App dies with `streamlit: not found` (exit 127). Run `python -c "import streamlit"` (or `dash`, `flask`, `gradio`, `fastapi`; `node -v` for Vite) in the Workspace. If it fails: an environment that has the package (best), `requirements.txt` at the project root, or a `pip install` at the top of `app.sh` for a prototype; trade-offs in [domino-apps/FRAMEWORKS.md](../domino-apps/FRAMEWORKS.md#dependencies).
+ 6. Finish with the post-initialization checklist.
## Reference snippets
- ### React / Vite: `vite.config.js`
+ ### Dash: `app.py` (Dash 3 removed `run_server`)
- ```javascript
- import { defineConfig } from 'vite'
- import react from '@vitejs/plugin-react'
+ ```python
+ import os
+ from dash import Dash, html
- export default defineConfig({
- plugins: [react()],
- base: './',
- server: { host: '0.0.0.0', port: 8888, strictPort: true },
- preview: { host: '0.0.0.0', port: 8888, strictPort: true },
- build: { outDir: 'dist', assetsDir: 'assets' }
- })
+ app = Dash(__name__, routes_pathname_prefix="/",
+ requests_pathname_prefix=os.environ.get("DOMINO_RUN_HOST_PATH"))
+ app.layout = html.Div([html.H1("Domino Dash App")])
+
+ if __name__ == "__main__":
+ app.run(host="0.0.0.0", port=8888, debug=False)
```
- ### React / Vite: `app.sh`
+ ### Flask: `app.py` and `app.sh`
- ```bash
- #!/bin/bash
- set -e
- cd /mnt/code
- npm ci
- npm run build
- npx serve -s dist -l 8888 --no-clipboard
- ```
+ ```python
+ from flask import Flask, request
- ### Streamlit: `app.sh`
+ app = Flask(__name__)
+ @app.route("/")
+ def index():
+ return f"Hello {request.headers.get('domino-username', 'Anonymous')}"
+
+ if __name__ == "__main__":
+ app.run(host="0.0.0.0", port=8888, debug=False)
+ ```
+
```bash
#!/bin/bash
set -e
- streamlit run app.py \
- --server.port 8888 \
- --server.address 0.0.0.0 \
- --server.headless true
+ cd "$(dirname "$0")"
+ python app.py
```
- ### Dash: `app.py`
+ ### Gradio: `app.py` (same `app.sh` as Flask)
```python
import os
- from dash import Dash, html
+ import gradio as gr
- app = Dash(__name__)
- app.layout = html.Div([html.H1("Domino Dash App")])
+ demo = gr.Interface(fn=lambda text: text, inputs="text", outputs="text")
- if __name__ == '__main__':
- app.run_server(host='0.0.0.0', port=8888, debug=False)
+ if __name__ == "__main__":
+ demo.launch(server_name="0.0.0.0", server_port=8888,
+ root_path=os.environ.get("DOMINO_RUN_HOST_PATH", ""))
```
- ### Flask: `app.py` and `app.sh`
+ ### FastAPI: `app.py` and `app.sh`
```python
- import os
- from flask import Flask
+ from fastapi import FastAPI
- app = Flask(__name__)
+ app = FastAPI()
- @app.route('/')
+ @app.get("/")
def index():
- return "Domino Flask App"
-
- if __name__ == '__main__':
- app.run(host='0.0.0.0', port=8888, debug=False)
+ return {"message": "Domino FastAPI App"}
```
```bash
#!/bin/bash
set -e
- python app.py
+ cd "$(dirname "$0")"
+ uvicorn app:app --host 0.0.0.0 --port 8888
```
- ### Gradio: `app.py` (use the Flask `app.sh` above)
+ ### Model endpoint call (any Python framework)
```python
- import gradio as gr
-
- demo = gr.Interface(fn=lambda text: text, inputs="text", outputs="text")
-
- if __name__ == '__main__':
- demo.launch(server_name='0.0.0.0', server_port=8888)
+ import os, requests
+ token = os.environ["MODEL_API_TOKEN"]
+ resp = requests.post(os.environ["MODEL_API_URL"], auth=(token, token), # synchronous endpoint
+ json={"data": {"feature1": 1.0}}, timeout=60)
```
+ Synchronous endpoints: HTTP Basic with the token as username and password; asynchronous: `Authorization: Bearer`. `server.js` in the React template does the same.
+
## Post-initialization checklist
Tell the user to:
- 1. Configure environment variables in the Domino project settings.
- 2. Set `app.sh` as the app entry point when publishing the app.
- 3. Test locally with `./app.sh` before deploying.
- 4. Confirm the app listens on port 8888.
+ 1. Set `MODEL_API_URL` and `MODEL_API_TOKEN` (if used) in the project's environment variables (see Inputs for where each comes from).
+ 2. Make sure the framework is in the App's environment (step 5), not only the Workspace.
+ 3. **Sync before publishing.** An App runs the project's committed files, not the Workspace's working copy. DFS project: **File Changes > Sync to Domino** (or the bundled MCP server's upload tool), then check `app.sh` and `app.py` under **Code**. Git-based: `git add`, `git commit`, `git push` from the Workspace terminal. Creating the version over the API right after an upload: pin `content.dfsCommitId` to the uploaded commit ([domino-apps/API-APPS.md](../domino-apps/API-APPS.md)).
+ 4. Optional start check in the Workspace, on another port (8888 is the IDE's) and in one command: the one-liner in [domino-apps/FRAMEWORKS.md](../domino-apps/FRAMEWORKS.md#streamlit). Keep 8888 in `app.sh` for the App container.
+ 5. Open **App Preview** in the workspace, select `app.sh`, and test: it runs the latest committed code in the real App runtime with the proxy prefix.
+ 6. **Publish App**, then **Deploy** the version from the App details page and set sharing.
- For deployment details, CI/CD, and proxy troubleshooting, use the `domino-apps` skill. If the app
- shows 404s or blank pages after publishing, use the `domino-debug-proxy` skill.
+ Deployment, CI/CD and framework details: `domino-apps`; 404s, blank pages or routing problems after publishing: `domino-debug-proxy`; Domino design system SPA: `domino-ui-bootstrap`.