Deploy Python (FastAPI, Flask, Django) with AI in one pass

How BrewInTH builds and starts a Python app, the file layout it expects, DATABASE_URL, a five-point Django checklist, and a prompt for your AI.
AI writes Python very well. Ask for an API in FastAPI or a back office in Django and it runs on your own machine within minutes. Getting it online is where people get stuck on the same questions: gunicorn or uvicorn, which port, how to reach the database, and why Django answers with DisallowedHost.
This guide explains how BrewInTH builds and runs a Python project, what the files should look like so the first deploy passes, the checklists for FastAPI, Flask and Django, and a prompt that lets your AI do it all.
In short
✅ With arequirements.txtat the project root, the platform knows it is Python and installs the packages during the build
✅ No start command needed when the files follow a known layout:main.py(FastAPI),app.py(Flask), ormanage.py+ the folder withwsgi.py(Django)
✅ Read the database from theDATABASE_URLthe platform sets; no passwords in code, and no SQLite file next to the code
✅ Django needsALLOWED_HOSTS,CSRF_TRUSTED_ORIGINSand a release command that runs migrate
✅ If the first try fails, open the log, find[app output], and let the AI fix it
How BrewInTH runs a Python project
When your AI uploads the code as a ZIP, the platform does three things:
- Works out the technology. If the project was created with Let the platform decide (recommended), it looks at the files at the root: a
requirements.txtorpyproject.tomlmeans Python. - Builds. It creates a virtual environment and runs
pip install -r requirements.txt(with only apyproject.toml, it installs withpip install .). - Starts the app. If you set no start command, it picks one from the files it finds, as in the picture below.

The platform also looks inside the file to see which framework it holds: a Flask main.py starts with gunicorn, a FastAPI app.py with uvicorn. Every variant listens on 0.0.0.0 and the port from the PORT variable for you, so there is no uvicorn.run(...) to write and no port to hard-code.
One thing to remember: the application variable must be named app (app = FastAPI() or app = Flask(__name__)). If your layout matches none of these, set a Start command yourself under the Releases tab › Advanced options (build / start / port).
Preparing the project to pass in one go
These apply to every framework:
requirements.txtat the root of the ZIP, not inside a nested folder, listing every package the code imports, includinggunicornoruvicorn. With Poetry or Pipenv, have the AI export arequirements.txt.- Leave out what the build does not need:
venv/,.venv/,__pycache__/,.git/and any.envfile. - Secrets go in the App settings tab, e.g.
SECRET_KEYor API keys, and the code reads them withos.environ. - Only
/tmpand/dataare writable. The code folder is read-only while the app runs. Files your users upload belong under/data(switch on Persistent storage (/data) in the App settings tab first);/tmpis emptied whenever the app restarts. - Readiness check. The platform opens
/and needs a 2xx or 3xx. An API with no/page should add/healthand set it in Health check path (in the advanced options of the Releases tab).
The database: read DATABASE_URL
Once the project has a database, the platform writes the connection into the app's settings: DATABASE_URL for PostgreSQL and MYSQL_URL for MySQL / MariaDB. The value looks like postgresql://user:pass@host:5432/dbname.
- Regular SQLAlchemy and psycopg take
DATABASE_URLas it is. - Async SQLAlchemy: have the code change the prefix to
postgresql+asyncpg://first. - MySQL with SQLAlchemy: change
mysql://tomysql+pymysql://. - Django: read
DATABASE_URLinsettings.pywith thedj-database-urlpackage.
Do not use a SQLite file next to the code (such as Django's default db.sqlite3): the code folder is not writable and the data would be lost on the next deploy. A site in real use should run on PostgreSQL. Not sure which engine to pick? Read which database should you pick?
If you create the database after the site is already live, deploy once more so the app sees the connection.
FastAPI and Flask
These two are the easiest. The minimum layout is:
main.py ← app = FastAPI() (Flask may use app.py)
requirements.txt ← fastapi, uvicorn[standard], and whatever else you use
When the project grows into an app/main.py layout, the platform knows that too (also the folders src/, api/, backend/ and server/).
If Alembic creates your tables, set the Release command to python -m alembic upgrade head. The platform runs it from the new code before visitors are moved to the new version; if it fails, the current version keeps serving.
Django: five things to set
Django runs well here, but it has production settings an AI often forgets.

ALLOWED_HOSTSmust contain the project's site address (and your own domain, if any), or you get DisallowedHost. Read it from the app's settings so a change of address needs no code change.CSRF_TRUSTED_ORIGINSneedshttps://your-site-address, or forms and the admin answer "CSRF verification failed". Also addSECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https"), because BrewInTH terminates HTTPS and forwards the request to the app.- Database: read
DATABASE_URLwithdj-database-urlinstead of SQLite. - Migrate: set the Release command to
python manage.py migrate --noinput, so the tables are ready before the site opens, every time. - Static files (the admin's CSS): use
whitenoise, and have the AI runpython manage.py collectstatic --noinputbefore making the ZIP and include the resulting folder in it.
Do not forget DEBUG = False, and keep SECRET_KEY in the App settings tab, not in the code.
On layout: manage.py must sit at the root of the ZIP, with exactly one folder holding wsgi.py (the project's settings folder, e.g. config/). The platform then starts it with gunicorn by itself.
A prompt that makes the AI deploy it
For an AI that works on your computer (Claude Code, Codex, Cursor, Windsurf), after you gave it the project's link and token:
Deploy this Python project to BrewInTH so that it passes on the first try.
1. Make sure requirements.txt is at the root and lists every imported package (including gunicorn / uvicorn).
2. The application variable must be named app and the layout must match what BrewInTH starts
automatically; otherwise set a start command.
3. Read the database from DATABASE_URL only. No SQLite file next to the code.
4. For Django: set ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS, SECURE_PROXY_SSL_HEADER, use whitenoise,
run collectstatic before zipping, and set the release command to migrate.
5. Every secret is a project secret. No .env, venv or __pycache__ in the ZIP.
6. Deploy, then check the live home page and a page that uses the database (use site_check).
7. If it fails, read the [release command], [readiness] and [app output] log lines and tell me
the cause before fixing. Never delete database data.
No coding agent: send the ZIP yourself
If a chat AI gave you the code as a ZIP, the Upload and go live page (BETA) takes it: create a project, choose it, and send the ZIP. The platform reads the code and sets several things for you, such as Django's migrate command, a SECRET_KEY that has no value yet, and the site address in ALLOWED_HOSTS / CSRF_TRUSTED_ORIGINS when the code reads those from variables. If the release fails, the page shows the cause for you to copy back to the AI.
Background work and scheduled jobs
An app on BrewInTH has one process: the web server. A worker that must keep running (a Celery worker, say) has nowhere to run on its own. What works is the Schedules tab of the project: run a command such as python manage.py send_reminders as often as every 5 minutes, up to 10 schedules per project. Small tasks that follow a response can use FastAPI's BackgroundTasks.
Common problems
ModuleNotFoundErrorin[app output]: the package is missing fromrequirements.txt.start_command_required: the platform found no entry point. Movemain.py/app.pyto the root or set a start command.- DisallowedHost / CSRF verification failed: see Django points 1-2.
[readiness]shows 404: the API has no/page; set the health check path to/health.- Cannot connect to the database at
localhost: the code hard-codes the address; readDATABASE_URLinstead. - The app exits for lack of memory: the free plan has 256 MB of RAM. Heavy libraries such as pandas or ML models may need a bigger plan.
Reading logs is covered in detail in Deploy failed? Let AI read the logs and fix it.
FAQ
Do gunicorn and uvicorn have to be in requirements.txt?
Always list them, so it is clear which server and version the app uses: uvicorn[standard] for FastAPI, gunicorn for Flask and Django.
Do other frameworks, such as Streamlit, work?
The platform starts only the layouts in this guide by itself. Any other framework needs its own Start command that listens on 0.0.0.0 and the port from the PORT variable. We have not tested every framework; if it does not come up, have the AI read the log.
How do I create a Django superuser?
Have the AI run a command in the app once the site is live, e.g. python manage.py createsuperuser --noinput, after setting the name and password as app settings (DJANGO_SUPERUSER_USERNAME, DJANGO_SUPERUSER_PASSWORD, DJANGO_SUPERUSER_EMAIL).
Why is the first visit slow?
On the free plan an app sleeps after a quiet spell, so the first visitor waits a moment while it wakes. Paid plans can turn sleeping off.
Can I do this from a phone?
You can watch the status and logs from a phone, but having an AI deploy code from a phone is not stable yet. Use a computer.
Summary
Python on BrewInTH needs no server setup of your own. Put requirements.txt at the root, follow a layout the platform knows, read the database from DATABASE_URL, and write no files outside /data: that is all FastAPI and Flask need. Django adds five things: ALLOWED_HOSTS, CSRF, the database, migrate and static files.
Start your first project free →
