Skip to content

Repository files navigation

🧱 Pyforge

Pyforge

Pyforge is a modern FastAPI backend starter template designed for production-grade Python 3.14+ development. It's built with clean architecture, async-first design, and developer experience in mind — featuring uv, Ruff, SQLAlchemy 2.0, Pydantic v2, and structured logging out of the box.

PythonuvFastAPIUvicornSQLAlchemyAlembicPydanticRuffpytesthttpxstructlogDockerGitHub Actions


🚀 Key Features

Modern Stack

  • Python 3.14 + uv for reproducible, lightning-fast dependency management
  • Async-first FastAPI + Uvicorn for high performance
  • SQLAlchemy 2.0 async ORM with Alembic migrations
  • Pydantic v2 and pydantic-settings for configuration
  • Ruff for linting, formatting, and static type checks
  • pytest + httpx for async testing
  • structlog for production-ready structured logging
  • Docker for containerization
  • GitHub Actions CI for automatic quality checks

Clean Architecture

src/app/
├── api/ # Routes + dependency wiring
├── core/ # Config, logging, security, rate limiting
├── db/ # DB engine, sessions, migrations
├── models/ # ORM entities
├── schemas/ # Pydantic models
├── services/ # Business logic
├── exceptions/ # Custom errors & handlers
└── tests/ # Unit and integration tests

🧰 Getting Started

1. Install uv

uv replaces pip, virtualenv, and poetry with one fast tool. Follow official installation:

curl -LsSf https://astral.sh/uv/install.sh | sh

2. Clone and bootstrap the template

git clone https://github.com/helioLJ/pyforge.git
cd pyforge
uv sync

💡 Recommendation: Always pin Python to 3.14+ in your .tool-versions or pyproject.toml for consistency.

3. Run the app

# Option 1: Using FastAPI CLI (simpler)
uv run fastapi run src/app/main.py --reload
# Option 2: Using uvicorn directly (more control)
PYTHONPATH=src uv run uvicorn app.main:app --reload

Your API will be live at: 👉 http://localhost:8000/docs


⚙️ Configuration

All configuration is handled through pydantic-settings.

Default .env.example

DATABASE_URL=sqlite+aiosqlite:///./pyforge.dbDEBUG=FalseAPP_NAME=Pyforge

Guidelines

  • Never hardcode secrets in code; always use .env or secret managers.
  • Use model_config = SettingsConfigDict(env_file=".env") to load automatically.
  • For multiple environments, use .env.development, .env.staging, .env.production.

🪵 Logging

Pyforge uses structlog for JSON-formatted structured logging, ideal for observability platforms like Grafana or Datadog.

Recommendations

  • Use contextual loggers (structlog.get_logger().bind(request_id=...)).
  • Keep logs structured, not human-formatted.
  • Use INFO in production and DEBUG in development.
  • Avoid print() entirely — always log.

Example:

importstructloglog=structlog.get_logger()
log.info("user.created", user_id=123, email="john@example.com")

🧠 Architecture Guidelines

Clean Architecture Layers

LayerPurposeExample Folder
DomainEntities / Modelsapp/models
ApplicationBusiness logicapp/services
InfrastructureDatabase, logging, configapp/core, app/db
InterfaceAPI endpointsapp/api

✅ Keep dependencies inward only — outer layers depend on inner ones. ✅ Avoid circular imports by organizing feature modules clearly. ✅ Each domain (e.g. users, todos) should have its own schema, service, and router file.


🧪 Testing

Run tests

uv run pytest -v

Recommendations

  • Use pytest-asyncio for async endpoints.

  • Group tests under src/app/tests/.

  • Prefer httpx.AsyncClient with ASGITransport for integration tests:

    fromhttpximportAsyncClient, ASGITransportfromapp.mainimportapp@pytest.mark.asyncioasyncdeftest_health():
    asyncwithAsyncClient(transport=ASGITransport(app=app), base_url="http://test") asac:
    res=awaitac.get("/health")
    assertres.status_code==200
  • Always test both happy-path and error scenarios.

  • Use fixtures for database sessions and mock data.


🧹 Code Quality

Ruff (Linter + Formatter + Type Checker)

Run checks and formatting:

uv run ruff check .
uv run ruff format .

Guidelines

  • Stick to 100-char lines (line-length = 100).
  • Let Ruff handle formatting automatically.
  • Run Ruff before committing (pre-commit configured).
  • Use type annotations everywhere; Ruff's type rules (--select TYP) ensure type safety.

🔄 Pre-Commit Hooks

Set up once:

pre-commit install

Hooks included:

  • Ruff linting & formatting
  • Pyupgrade (ensures Python 3.14 syntax)

Run manually:

pre-commit run --all-files

🧱 Database and Migrations

Initialize Alembic

uv run alembic init src/app/db/migrations

Create a migration

uv run alembic revision --autogenerate -m "create users table"

Apply migrations

uv run alembic upgrade head

Recommendations

  • Always commit migrations with code changes.
  • Avoid editing Alembic scripts manually unless absolutely necessary.
  • Use descriptive revision messages.

🧪 CI/CD

Pyforge ships with GitHub Actions configured for:

  • ✅ Linting (ruff check)
  • ✅ Type checks (ruff check --select TYP)
  • ✅ Testing (pytest)
  • ✅ Packaging (uv build)

Example: .github/workflows/ci.yml

name: CIon: [push, pull_request]jobs:
test:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v3
- run: uv sync
- run: uv run ruff check .
- run: uv run pytest -q

Recommendations

  • Keep CI fast: don't rebuild Docker here unless required.
  • Extend with deploy stage only in private/prod repos.
  • Store secrets in GitHub Encrypted Secrets, never in .env.

🐳 Docker Setup

Build and run locally

docker compose up --build

Guidelines

  • Use multi-stage builds for smaller images.
  • Base image: python:3.14-slim.
  • Always set PYTHONUNBUFFERED=1 for real-time logs.
  • Use uv inside Docker for consistent deps.
  • Expose port 8000 (FastAPI default).

🧭 Development Workflow

  1. Create your feature branch

    git checkout -b feat/add-auth
  2. Run app

    uv run fastapi run src/app/main.py --reload
  3. Test before commit

    uv run pytest
    pre-commit run --all-files
  4. Push and PR GitHub Actions will validate code automatically.


🧩 Extending Pyforge

Pyforge is intentionally modular. You can easily extend or replace components:

ComponentDefaultAlternative Options
CI/CDGitHub ActionsGitLab CI, CircleCI
ORMSQLAlchemyTortoise ORM, GINO
LoggerstructlogLoguru (simpler dev)
AuthJWT via FastAPIOAuth2, Firebase
Configpydantic-settingsDynaconf, Environs
DeploymentDockerPulumi, ECS, Cloud Run

🧠 Recommended Practices

  • Always use async DB clients to avoid blocking the event loop.
  • Avoid time.sleep() — use await asyncio.sleep().
  • Keep endpoints slim — delegate logic to services/.
  • Validate everything in Pydantic models, not route logic.
  • Use dependency injection (Depends) for shared logic (DB, rate limiters, auth).
  • Configure structured logs and metrics early — it's harder later.
  • Follow semantic versioning for template updates.

📜 License

MIT License © 2025 [helioLJ]

You're free to fork, modify, and use Pyforge in commercial or open-source projects. Just keep the license notice and share improvements if you can 💡


💬 Contributing

Contributions welcome!

  1. Fork the repo
  2. Create a feature branch (feat/something)
  3. Follow the code style (uv run ruff format .)
  4. Add tests for new features
  5. Submit a PR

For large contributions, open an issue first to discuss design direction.


🧩 Summary

CategoryToolNotes
Package MgmtuvFast, reproducible, modern
FrameworkFastAPIAsync, type-safe web framework
ORMSQLAlchemyAsync ORM with migrations
ValidationPydantic v2Type-driven schemas
LoggingstructlogJSON structured logging
Lint/FormatRuffUnified code quality tool
Testingpytest, httpxAsync testing
CI/CDGitHub ActionsOptional, modular
DeploymentDockerProduction ready

About

Production-ready FastAPI backend starter template with Python 3.14+, SQLAlchemy 2.0, Pydantic v2, and clean architecture

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages