A robust FastAPI application demonstrating user registration, JWT authentication (including refresh tokens), and a flexible repository pattern supporting SQLite, PostgreSQL, and MongoDB backends.
This project serves as a template or starting point for building secure and scalable FastAPI applications with a focus on:
- Clean Architecture: Separation of concerns using API routes, core logic, database repositories, and Pydantic schemas.
- Flexibility: Easily switch between SQL (SQLite/PostgreSQL) and NoSQL (MongoDB) databases via configuration.
- Modern Tooling: Utilizes
uvfor dependency management,Dynaconffor configuration, andrufffor linting/formatting. - Testability: Designed with dependency injection and includes a comprehensive test suite using
pytest.
- JWT-based authentication (login, refresh tokens).
- User registration with password hashing (bcrypt) and validation.
- Protected user profile endpoint (
/users/me). - Flexible database layer using the Repository Pattern.
- Configuration management with
Dynaconf(settings.toml,.secrets.toml, environment variables withFAPI_prefix). - Asynchronous support throughout (FastAPI, database drivers).
- Automated API documentation (Swagger UI & ReDoc).
- Comprehensive test suite with
pytest(including coverage). - Health check endpoint (
/health).
Below is an overview of the application's architecture:
- Python: >= 3.13
- Framework: FastAPI (>=0.115.12)
- Authentication: python-jose (JWT), passlib, bcrypt
- Database ORM/Driver:
- SQLAlchemy (>=2.0.40) for SQL databases
- Motor (>=3.5.0, via
mongodb_repository.py, requires separate install if used) for MongoDB - Psycopg2 (requires separate install if using PostgreSQL)
- aiosqlite (>=0.20.0, requires separate install if using async SQLite
sqlite+aiosqlite)
- Configuration: Dynaconf (>=3.2.0)
- Testing: pytest, pytest-asyncio, pytest-cov, httpx
- Dependency Management: uv
- Linting/Formatting: Ruff
/
├── app/ # Main application module
│ ├── api/ # API endpoints (routers)
│ ├── core/ # Core logic (config, security, exceptions)
│ ├── db/ # Database interaction layer (repositories, models, session)
│ └── schemas/ # Pydantic schemas (data validation)
├── config/ # Configuration files
│ ├── .secrets.toml # Secret settings (JWT secret, DB passwords) - DO NOT COMMIT
│ ├── .secrets.toml.example # Example secrets file
│ └── settings.toml # Main application settings (DB type, etc.)
├── tests/ # Application tests (mirrors app structure)
│ └── conftest.py # Pytest configuration and fixtures
├── .gitignore # Git ignore rules
├── main.py # FastAPI application entry point
├── pyproject.toml # Project metadata and dependencies (uv)
├── README.md # This file
├── run_tests.sh # Helper script for running tests
├── test.db # Default SQLite database file (if used)
└── uv.lock # Lock file for dependencies (uv)
Below is a preview of the application's interface:
-
Clone the repository:
git clone <your-repo-url> cd fapi
-
Create and activate a virtual environment:
python -m venv .venv source .venv/bin/activate # On Windows use `.venv\Scripts\activate`
-
Install dependencies (using uv):
# Install core dependencies uv pip install -e . # Install all dependencies including test extras uv pip install -e '.[test]' # Install DB-specific drivers if needed (not included by default) # uv pip install psycopg2-binary # For PostgreSQL # uv pip install motor # For MongoDB # uv pip install aiosqlite # For async SQLite
-
Configure Settings:
-
Settings are managed by
Dynaconf, loading fromconfig/settings.toml,config/.secrets.toml, and environment variables (prefixed withFAPI_, e.g.,FAPI_DATABASE_TYPE,FAPI_JWT_SECRET_KEY). -
Create
config/.secrets.tomlby copyingconfig/.secrets.toml.example. Add yourJWT_SECRET_KEY(must be strong and secret). Do not commit.secrets.toml.# config/.secrets.toml [default] JWT_SECRET_KEY="your_super_secret_strong_key_here_min_32_chars" # Optional: Add sensitive DB credentials if not using env vars # SQL_DATABASE_URL="postgresql+asyncpg://user:pass@host:port/dbname" # MONGO_DATABASE_URL="mongodb://user:pass@host:port/"
-
Edit
config/settings.tomlto select your database backend:- Set
database_typeto"sqlite","postgres", or"mongodb". - Ensure the corresponding database URL (
sql_database_urlormongo_database_url) is correctly set (either here, in.secrets.toml, or via environment variables likeFAPI_SQL_DATABASE_URL). The default usestest.db. - If using MongoDB, set
mongo_db_name.
- Set
-
-
Initialize Database:
- SQL (SQLite/PostgreSQL): This project includes
alembicas a dependency for potential migrations.- Ensure your database exists.
- If you have Alembic migrations set up (e.g.,
alembic.inifile and amigrations/directory), run:alembic upgrade head - (If Alembic is not fully configured, you may need to initialize it or manage schema changes manually)
- MongoDB: Ensure your MongoDB server is running. The application will automatically attempt to create the required unique indexes for the
userscollection (onusernameandemail) when it starts up, using the database name specified bymongo_db_namein your settings.
- SQL (SQLite/PostgreSQL): This project includes
uvicorn main:app --reload --host 0.0.0.0 --port 8000The API will be available at http://localhost:8000.
Ensure test dependencies are installed (uv pip install -e '.[test]').
Using the helper script:
chmod +x run_tests.sh
./run_tests.shThis script provides options for different test runs (verbose, coverage, etc.).
Using pytest directly:
# Run all tests (verbose)
PYTHONPATH=. pytest -v
# Run tests with coverage report
PYTHONPATH=. pytest --cov=app --cov-report=term-missing --cov-report=htmlCoverage report will be in the htmlcov/ directory.
If you have act installed, you can simulate GitHub Actions workflows locally. This is particularly useful for testing CI/CD pipelines before pushing changes.
# Run workflows, specifying architecture if needed (e.g., for M1/M2 Macs)
act --container-architecture linux/amd64Once the server is running, access the interactive API documentation:
- Swagger UI:
http://localhost:8000/docs - ReDoc:
http://localhost:8000/redoc
- Stop the application.
- Update
config/settings.tomlor environment variables:- Change
database_type. - Ensure the correct URL (
sql_database_urlormongo_database_url) is set. - Update
mongo_db_nameif switching to MongoDB.
- Change
- Ensure the target database server (PostgreSQL or MongoDB) is running and accessible.
- If switching to SQL, ensure the database exists and migrations are applied (
alembic upgrade head). - If switching to MongoDB, ensure indexes exist.
- Restart the application:
uvicorn main:app --reload ...


