Project Structure Requirements
How Phemeral detects your project root, dependencies, and application entry point.
Phemeral analyzes your repository to determine how to build and run your application. This page describes what Phemeral looks for and how to structure your project for successful detection.
Project Root Detection
The project root is the directory that contains your dependency file. Phemeral searches for dependency files in this priority order:
uv.lockpoetry.lockpyproject.tomlrequirements.txt
The search walks the directory tree from the repository root, favoring files at shallower depths. The directory containing the first matching file becomes the project root.
If autodetection picks the wrong service in a monorepo, you can override it in your project's Root Directory setting. See Set a Custom Root Directory.
Example
Given this repository structure:
my-repo/
├── README.md
├── backend/
│ ├── pyproject.toml
│ ├── uv.lock
│ └── app/
│ └── main.py
└── frontend/
└── ...Phemeral finds uv.lock at backend/uv.lock and sets the project root to backend/.
Custom Root Directory Override
When you save a custom root directory in project settings, Phemeral starts detection from that repository-relative directory instead of from the repository root.
Inside the selected directory, Phemeral keeps the same dependency priority rules:
uv.lockpoetry.lockpyproject.tomlrequirements.txt
This lets you deploy a specific service from a monorepo without restructuring the repository.
Directory Structure Examples
FastAPI with uv
my-project/
├── .python-version
├── pyproject.toml
├── uv.lock
└── app/
└── main.py # app = FastAPI()Flask with poetry
my-project/
├── .python-version
├── pyproject.toml
├── poetry.lock
└── app/
└── main.py # app = Flask(__name__)Django with pip
my-project/
├── .python-version
├── requirements.txt
└── myproject/
├── manage.py
├── myproject/
│ ├── settings.py
│ ├── urls.py
│ └── asgi.py # application = get_asgi_application()
└── myapp/
└── ...Monorepo (Backend in Subdirectory)
my-repo/
├── frontend/
│ └── ...
└── backend/
├── pyproject.toml
├── uv.lock
└── app/
└── main.py # app = FastAPI()Phemeral detects backend/ as the project root because uv.lock is located there.
Python Version
Place a .python-version file at or near your project root containing the Python version:
3.11Phemeral searches for this file starting at the project root. If not found, Python 3.12 is used as the default.
Application Entry Point
Phemeral scans .py files in your project for framework instantiation.
Ensure your framework instance is assigned to a module-level variable:
# app/main.py
from fastapi import FastAPI
app = FastAPI() # Phemeral detects "app" as the object name
@app.get("/")
def read_root():
return {"message": "Hello, World!"}Checklist
Before deploying, verify that your project includes:
- A dependency file (
uv.lock,poetry.lock,pyproject.toml, orrequirements.txt) - A
.pyfile that imports and instantiates a supported framework (FastAPI, Flask, or Django) - The framework instance is assigned to a module-level variable
- Optionally, a
.python-versionfile specifying your Python version - If needed, a custom root directory saved in project settings for monorepo or multi-service repositories