fastapi-foundry
fastapi-foundry is a command-line tool that scaffolds new FastAPI projects in seconds.
One command gives you a ready-to-run FastAPI application with a clean app/ layout,
a modern uv-compatible pyproject.toml, environment-based
configuration and a sensible .gitignore, so you can skip the boilerplate and start
building your API.
uvx fastapi-foundry init myproject
Features
- One-command setup:
fastapi-foundry init <name>creates a complete project. - Runs immediately: the generated app starts with
uv syncanduvicorn, no edits needed. - Structured by default: routes in
app/routes.pydelegating to controller classes inapp/controller/. - Safe by default: never overwrites an existing directory and rejects unsafe project names.
- Same commands every time: the run command is
uvicorn app.routes:appin every generated project. - Database ready: a SQLAlchemy engine and a
get_dbsession dependency, connecting to MySQL through PyMySQL with credentials from.env.
Requirements
- Python 3.12 or newer
- uv (recommended) or pip
Install uv if you don't have it yet:
# macOS and Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Installation
Option 1: Run without installing (recommended)
uvx downloads and runs the latest version in a temporary environment:
uvx fastapi-foundry init myproject
Option 2: Install as a global command
uv tool install fastapi-foundry
Then use it from any directory:
fastapi-foundry init myproject
Upgrade later with:
uv tool upgrade fastapi-foundry
Option 3: Install with pip
pip install fastapi-foundry
Quick start
1. Create a project
uvx fastapi-foundry init myproject
Created FastAPI project: myproject
Next steps:
cd myproject
uv sync
uv run uvicorn app.routes:app --reload
2. Install dependencies
cd myproject
uv sync
3. Run the application
uv run uvicorn app.routes:app --reload
4. Open it in your browser
| URL | Description |
|---|---|
| http://127.0.0.1:8000 | API root, returns {"message": "Hello from FastAPI"} |
| http://127.0.0.1:8000/docs | Interactive Swagger UI documentation |
| http://127.0.0.1:8000/redoc | ReDoc documentation |
Generated project structure
myproject/
├── pyproject.toml # Dependencies (FastAPI, Uvicorn, SQLAlchemy, PyMySQL)
├── .env # Your local environment variables (git-ignored)
├── .env.example # The same keys, committed for other developers
├── .gitignore # Python, uv and tooling ignores
├── README.md # How to install and run the project
└── app/
├── routes.py # FastAPI application and routes
├── config/
│ ├── app.py # APP_NAME and DEBUG
│ ├── database.py # DB_* settings and the DATABASE_URL built from them
│ └── sqlalchemy_connection.py # SQLAlchemy engine, SessionLocal and get_db
├── controller/
│ └── home_controller.py # Handles the default route
└── database/
└── 20260922143022_create_users_table.py
Generated projects are applications, not libraries: there is no [build-system] and no
__init__.py. app/ is a namespace package that uvicorn imports from the project root.
Routes stay thin and hand the work to a controller. The generated app/routes.py:
from fastapi import FastAPI
from app.config.app import APP_NAME, DEBUG
from app.controller.home_controller import HomeController
app = FastAPI(title=APP_NAME, debug=DEBUG)
home_controller = HomeController()
@app.get("/")
def root() -> dict[str, str]:
return home_controller.index()
And app/controller/home_controller.py:
class HomeController:
"""Handles requests for the application root."""
def index(self) -> dict[str, str]:
return {"message": "Hello from fastapi-foundry"}
Add a controller class per resource in app/controller/, and give it a route in
app/routes.py.
Configuration
Generated projects read their settings from environment variables, with one module per
kind of configuration in app/config/:
| Variable | Module | Default | Description |
|---|---|---|---|
APP_NAME |
app/config/app.py |
project name | Title shown in the API docs |
DEBUG |
app/config/app.py |
false |
Enables FastAPI debug mode (true, 1 or yes) and SQL logging |
DB_CONNECTION |
app/config/database.py |
mysql+pymysql |
SQLAlchemy dialect and driver |
DB_HOST |
app/config/database.py |
127.0.0.1 |
Database server host |
DB_PORT |
app/config/database.py |
3306 |
Database server port |
DB_DATABASE |
app/config/database.py |
project name in snake_case | Database name |
DB_USERNAME |
app/config/database.py |
root |
Database user |
DB_PASSWORD |
app/config/database.py |
empty | Database password |
DATABASE_URL |
app/config/database.py |
built from the DB_* settings |
Optional complete SQLAlchemy URL; overrides the DB_* settings when set |
Add new settings to the module they belong to, or create a new module in app/config/
for a new kind of configuration.
To load the values from the generated .env file, start the server with --env-file:
uv run uvicorn app.routes:app --reload --env-file .env
.env is git-ignored because it holds your own credentials. Every project also gets a
.env.example with the same keys and defaults, which is committed, so a developer who
clones the project creates their .env from it instead of guessing the key names:
cp .env.example .env
When you add a setting, add its key to .env.example as well.
Database connection
app/config/database.py builds DATABASE_URL from the DB_* settings, and
app/config/sqlalchemy_connection.py creates the SQLAlchemy engine from it and provides
get_db, a dependency that opens one session per request and closes it afterwards. The
default database name is the project name in snake_case (my-fastapi-app →
my_fastapi_app). Set your own credentials in .env:
DB_CONNECTION=mysql+pymysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=my_fastapi_app
DB_USERNAME=<user>
DB_PASSWORD=<password>
The URL is built with SQLAlchemy's URL.create, so special characters such as @, : or
/ in the username or password need no escaping. To supply a complete URL instead (for
example in Docker or CI), set DATABASE_URL; it takes precedence over the DB_* settings.
from typing import Annotated
from fastapi import Depends
from sqlalchemy.orm import Session
from app.config.sqlalchemy_connection import get_db
@app.get("/items")
def list_items(db: Annotated[Session, Depends(get_db)]) -> list[dict]:
...
The engine connects lazily, so the app starts even when the database is not reachable;
the first request that uses get_db is what opens a connection.
Project names
The project name is used for the folder and the distribution name, so it must:
- start with a letter
- contain only letters, digits, hyphens (
-) and underscores (_) - not be a Python keyword or clash with a standard library or FastAPI module (for example
jsonorfastapi)
uvx fastapi-foundry init my-fastapi-app
This creates the my-fastapi-app/ folder. The name does not appear inside the project, so
the run command is the same as for every other project:
uv run uvicorn app.routes:app --reload
If the target folder already exists, fastapi-foundry stops with an error instead of overwriting your files.
Command reference
fastapi-foundry --help # Show available commands
fastapi-foundry init --help # Show help for the init command
fastapi-foundry init <name> # Create a new project in the current directory
fastapi-foundry migration # Create a migration file in ./app/database
Migrations
Run fastapi-foundry migration from the project root to add a migration file:
uvx fastapi-foundry migration
Run from anywhere else (an unrelated folder, or a subfolder such as app/), it
stops with an error instead of creating files there. A project root is recognised
by its pyproject.toml and app/routes.py.
It asks whether the migration targets an existing table or a new one. For a new table it asks for the table name; for an existing table it lists the tables earlier migrations already cover so you can pick one.
Is this migration for an existing table or a new table?
1) Existing table
2) New table
Select [1-2]: 2
What is the name of the table this migration should structure: users
Created migration: app/database/20260922143022_create_users_table.py
Migration files are written to app/database/, alongside the users migration that every
new project ships with:
app/database/
├── 20260922143022_create_users_table.py
└── 20260922143512_create_posts_table.py
Each file records its table in a TABLE constant, which is how the command
lists existing tables. No database connection is needed. If you edit a TABLE
value by hand, keep it a valid table name; files with invalid names are left
out of the list.
"""Create table 'users'."""
TABLE = "users"
def upgrade() -> None:
"""Apply this migration."""
def downgrade() -> None:
"""Revert this migration."""
The upgrade() and downgrade() bodies are yours to fill in; fastapi-foundry
does not run migrations yet.
Roadmap
fastapi-foundry is in early development. Planned features include:
- Running migrations with Alembic
- Settings management with Pydantic Settings
- Generators for models and routes
- Authentication scaffolding
- Docker support
Contributing
Issues and pull requests are welcome on GitHub.
To set up a development environment:
git clone https://github.com/udarakalpana/fastapi-foundry.git
cd fastapi-foundry
uv sync
uv run pytest
Run the CLI from your local checkout:
uv run fastapi-foundry init myproject
Tip: create test projects outside the repository folder so they don't get mixed into its Git history.
License
fastapi-foundry is released under the MIT License.
Metadata
Release files for fastapi-foundry 0.7.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fastapi_foundry-0.7.0.tar.gz | 17.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fastapi_foundry-0.7.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 38.6 kB
Release files / fastapi_foundry-0.7.0.tar.gz
| Download URL | fastapi_foundry-0.7.0.tar.gz |
|---|---|
| Size | 17.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
481a493a8b1ba30790e7c9dcf47c2449580f966d759b47b95d3fc0560d8b7817
|
|
BLAKE2b-256 checksum How to use checksums |
9e752ae51865ffb9bc5fa4bf997e24a2fe55fbdba3b9b49a6417c301c4dd5e8a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / fastapi_foundry-0.7.0-py3-none-any.whl
| Download URL | fastapi_foundry-0.7.0-py3-none-any.whl |
|---|---|
| Size | 21.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8cb5b7c07a437bb2604407d94dd5ee9ef78ae4668ba660268cdbe8922ed10c52
|
|
BLAKE2b-256 checksum How to use checksums |
3e0a263a0d34bcf80e61eeec6f727eed5659c2716d3c0dae20dcc655461eaf75
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.22 {"installer":{"name":"uv","version":"0.12.22","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|