Deploying
Every scaffold ships deploy-ready: pick a static host for the build output, or run the live server on a platform that takes a Procfile.
Two ways to go live#
Koyo supports both of the common deployment shapes, and the scaffold includes the files for each.
-
Static hosting for sites with no dynamic routes:
run
koyoapp buildand point a CDN or static host at.koyo/build/site. No Python is needed at serving time. - Live server for dynamic routes (bracket segments) and session state: run the Koyo app under uvicorn. This is the path the rest of this page covers.
What the scaffold ships#
koyoapp create writes three deployment files into every
new project:
-
Procfilestarts the production server with a self-contained command:web: python -m uvicorn koyoapp.serve:app --host 0.0.0.0 --port $PORT -
requirements.txtpinskoyoappto the version that created the project, so the platform installs the same release you developed against. -
.railwayignorekeeps the local.venv, bytecode cache, and build output out of the upload, so containers build their own Linux environment. The same exclusions apply to any platform that rsyncs or zips the project directory.
Deploy to Railway#
Install the CLI, then from the project root:
brew install railway # or: npm i -g @railway/cli
railway login # opens your browser
railway init # creates and links a project
railway up # builds and deploys
railway domain # get a public URL, e.g. myapp.up.railway.app
Railpack detects Python from requirements.txt, installs
the pinned dependencies, and starts the web command from
the Procfile. Railway injects $PORT automatically, and
the app binds 0.0.0.0 in the Procfile so the platform
can reach it. Subsequent deploys are just railway up
again.
Deploy to Render#
Create a Web Service pointing at the project root and set:
- Build command:
pip install -r requirements.txt - Start command:
python -m uvicorn koyoapp.serve:app --host 0.0.0.0 --port $PORT
Render sets $PORT for you. The same start command works
on Fly.io, a VPS with a reverse proxy, or any platform that runs
Python processes.
Environment#
By default the server runs from the project root, so
serve.py resolves app/, public/,
and styles/ relative to the current directory. If the
platform runs from somewhere else, point it at the project root
explicitly:
KOYO_PROJECT_DIR=/path/to/project
Production mode is the default: without KOYO_DEV=1 the
live reload probe and script are not registered, and errors render the
generic page without a traceback.
Scaling and state#
Session state is in-memory only. It resets on restart and is not
shared across processes: run a single replica unless you move state
elsewhere. Static assets and the compiled styles/koyo.css
ship with the app, so the server needs no build step beyond
installing the pinned dependencies.