From IT

Give the intern the floor plan

Cowork, Claude, Cursor, and ChatGPT are sharp. They have also never walked this building. They assume Linux, Docker, and an app that lives at /. Yours lives at /apps/<slug>/ on Windows Server. Paste this briefing once — then the model writes something we can actually Deploy.

Download iVistaar

Where to hand it

  1. 01

    Cowork / Claude

    Project or chat instructions. The intern reads it before the first file.

  2. 02

    Cursor

    Drop it in .cursor/rules/ivistaar.mdc, or paste it into Rules.

  3. 03

    ChatGPT / Copilot

    Custom instructions, or the first message of the thread. Same briefing either way.

The briefing

Written so you can paste it without rewriting. IT already did the explaining.

Internal briefing

From
IT
To
The intern (Cowork, Claude, Cursor, ChatGPT, Copilot)
Re
This app does not live at /

Floor plan · read before generating code

You are helping me build a Python web app that will be deployed with iVistaar.

## What iVistaar is
iVistaar is an internal deployment control plane for Windows Server/IIS. It gives Flask, Dash, FastAPI, Streamlit, and Gradio apps an organization URL without Git, Docker, Linux, or any public cloud service. I connect a folder on the server, click Deploy, and the app appears at:

    http://<our-server>:8080/apps/<slug>/

The app never runs at the site root — it is always served under the /apps/<slug>/ path prefix by iVistaar's gateway.

## Runtime environment (assume all of this)
- Windows Server, Python 3.10+ (prefer 3.11–3.12 so pip wheels exist; do not require compiling pandas/numpy).
- The server is on our intranet. Do not rely on public internet at runtime: no CDN-hosted JS/CSS/fonts, no external API calls unless I explicitly allow them.
- Each app runs as its own Waitress process on a localhost port, behind iVistaar's reverse proxy. WebSockets work (Streamlit/Gradio) in service mode.
- No Git, no Docker, no systemd, no Linux-only commands or paths. Use pathlib / os.path, never hardcoded "/" or "\" separators.

## Entrypoint contract (iVistaar connects by module:variable)
- Flask: expose a WSGI object named `app` in app.py → entrypoint `app:app`.
- Dash: create `app = Dash(__name__)` and also set `server = app.server` at module scope → entrypoint `app:server` (or `run:server` if the file is run.py).
  - NEVER set requests_pathname_prefix, routes_pathname_prefix, or serve_locally yourself — iVistaar injects the /apps/<slug>/ prefix and forces serve_locally=True. Setting them breaks asset URLs.
- FastAPI: `app = FastAPI()` → entrypoint `app:app` (served via a2wsgi).
- Streamlit: the entrypoint is `streamlit:app.py` where app.py is the script path.
- Gradio: expose the interface as a module-level variable named `demo` → entrypoint `app:demo`.

## Code rules so the app works behind the /apps/<slug>/ prefix
1. Never hardcode absolute URL paths. No href="/...", src="/...", fetch("/..."), url_for with a leading assumption of root. Use relative URLs ("./...", "../...") or the framework's URL helpers.
2. All frontend→backend requests must be relative so they stay under the prefix.
3. Do not call app.run()/uvicorn.run()/demo.launch() at module import time. Guard dev servers under `if __name__ == "__main__":`. iVistaar imports the module; it must not block or bind a port on import.
4. Ship a requirements.txt. Prefer versions with prebuilt Windows wheels. If you use pandas/numpy, target Python 3.11–3.12.
5. Write files only inside the app folder. Log to stdout/stderr, not to fixed log paths.
6. Answer GET / quickly with HTTP 200 — iVistaar health-checks the app after deploy.
7. Keep secrets out of code; read them from environment variables.

## What happens when I click Deploy
iVistaar creates a virtualenv, installs requirements.txt, generates a wrapper (ivistaar_serve.py), starts a scheduled task named iVistaarApp-<slug>, and reverse-proxies /apps/<slug>/ to it. Redeploy restarts that task.

## Failure modes to avoid (these are the ones that actually happen)
- Dash stuck on "Loading…" → wrong entrypoint or missing `server = app.server`, or someone set the pathname prefix manually.
- "DashRenderer is not defined" → component JS requested from the wrong path; caused by hardcoded absolute asset URLs or manual prefix settings.
- pip tries to compile pandas / asks for Visual Studio → wrong Python version; use 3.11–3.12 and wheels.
- Streamlit loads but widgets freeze → needs WebSocket support; fine on iVistaar service mode, broken under plain IIS HttpPlatformHandler.
- WinError 32 on redeploy → the app kept a file open (often a log); close file handles, log to stdout.

When you generate code, follow the entrypoint contract and the prefix rules above. If a choice would only work at the site root, change it to work under /apps/<slug>/ instead.

Prefer a markdown file? Same briefing: customer-llm-instructions.md.

Why IT wrote this

The intern will happily generate a beautiful Dash app that only works at the site root, pull pandas on a Python with no wheels, and call app.run() on import. Then Deploy shows a white Loading… page and someone files a ticket.

This briefing is us helping the team before that ticket exists. One paste. Then the model aims at /apps/<slug>/, Waitress, and Windows from the first file.

If it still fails: troubleshooting covers the Windows modes we actually see — Dash Loading…, DashRenderer, pandas / Visual Studio.