Configuration
previewly.toml, previewly.yml, / previewly.yaml
Place exactly one repo-root file Previewly parses in this order: previewly.toml, previewly.yaml, then previewly.yml. Values override the Previewly API defaults applied to your organization.
Fields
| Key | Purpose |
|---|---|
| dockerfile | Optional path to a Dockerfile you authored (for example apps/web/Dockerfile). When present, Previewly asserts the file exists and deploys exclusively with this image specification. Omit it everywhere you rely on Previewly's inferred build or generated Dockerfile. |
| internal_port / port | TCP port listened to inside the container. Must mirror EXPOSE whenever you supply a Dockerfile, and aligns with Previewly-generated images too. |
| startup_command | Shell command Previewly invokes when emitting a Dockerfile for you—for example uvicorn app.main:app --host 0.0.0.0 --port $PORT or pnpm --filter ./site start in a turborepo. Overrides startup_file when both are present. |
| startup_file | Repo-relative file Previewly prefixes with node or python, depending on the resolved runtime hint, when startup_command is absent. |
| runtime | One of auto, next, node, python, go, static . Leave unset or specify auto to rely on heuristic detection rooted at the repository root (go.mod wins over package.json, Python markers take precedence beneath that, and so forth). Set manually when previews live in unconventional layouts Previewly cannot discover automatically. |
| gateway | Optional multi-route block for one preview URL routing to several loopback origins. Declare two or more gateway.routes[] rows with path_prefix, upstream_port (listen on 127.0.0.1 with ephemeral local ports—you are not exposing the VM's port 443 to FastAPI manually), startup_command, and strip_prefix toggling whether prefixes like /api are stripped upstream. Exactly one path_prefix = "/" catch-all fronts the SPA. Previewly emits nginx on your internal_port / Fly PORT. Ignored when you deploy via an explicit dockerfile path—author your own nginx then. |
| env | Runtime key/value pairs merged into Fly before HOST / HOSTNAME / PORT (which Previewly overwrites last). |
| build_args | Forwarded straight to Docker's --build-arg invocation when deploying a Dockerfile. |
| version | Optional documentation-only integer—you may omit it safely today because Previewly only validates known keys strictly. |
FastAPI preview without a Dockerfile
Commit requirements.txt. Keep internal_port aligned with whichever port uvicorn listens on—or pass Fly's forwarded $PORT so tweaks stay centralized.
internal_port = 8080
runtime = "python"
startup_command = "uvicorn app.main:app --host 0.0.0.0 --port $PORT"
[env]
DATABASE_URL = "postgresql+asyncpg://preview:[email protected]/preview-db"The generated image installs requirements.txt before running startup_command.
Front-end plus API sharing one HTTPS URL
Fly terminates TLS on HTTPS for visitors. Inside the ephemeral machine Previewly listens on plaintext HTTP matching your internal_port. Public browser traffic never hits upstream ports 8000 / 8090 directly—they are loopback TCP services consumed by nginx, so configuring "a UI on port 8000" versus "an API on HTTPS 443 outward" boils down to: bind the SPA dev server locally on 127.0.0.1:8000, expose the API on 127.0.0.1:8090, and expose /api externally through nginx. Use strip_prefix = false whenever your framework requires the `/api` prefix preserved.
internal_port = 8080
[[gateway.routes]]
path_prefix = "/api"
upstream_port = 8090
strip_prefix = true
startup_command = "uvicorn app.main:app --host 127.0.0.1 --port 8090"
[[gateway.routes]]
path_prefix = "/"
upstream_port = 8000
strip_prefix = true
startup_command = "npm run preview -- --host 127.0.0.1 --port 8000"Visit https://….fly.dev/ for the UI and https://….fly.dev/api/... for FastAPI endpoints (prefix behavior depends on strip_prefix).
YAML example
version: 1
runtime: auto
startup_command: >-
npm run prisma:deploy && npm run start
internal_port: 8080
env:
DATABASE_URL_POOLER: postgres://preview:******@neon.tech/pooler
LOG_LEVEL: info
build_args:
PNPM_VERSION: "9"Omit dockerfile on purpose so Previewly emits a Dockerfile if none resides at your platform's conventional path (usually Dockerfile unless the Previewly deployment overrides it via environment).
TOML tables
version = 1
startup_file = "dist/server/index.js"
internal_port = 3000
[env]
LOG_LEVEL = "debug"
[build_args]
NPM_CONFIG_PRODUCTION = "false"Keep values string-shaped under [env] and [build_args] tables so parsing stays deterministic across YAML and TOML.