A modern REST API for a blog application with user authentication, CRUD operations, and JWT token-based security. Built with FastAPI and Neon PostgreSQL.
- User Authentication - Secure JWT-based authentication with refresh tokens
- User Management - Register, login, and user profile management
- Blog CRUD Operations - Create, read, update, and delete blog posts
- Role-Based Access Control - User roles (user, admin)
- Request Logging - Comprehensive logging for all API requests
- Error Handling - Standardized error responses with custom exceptions
- CORS Support - Cross-Origin Resource Sharing enabled
- Database Migrations - Automatic table creation on startup
- Health Check Endpoint - Monitor API availability
- Swagger Documentation - Auto-generated API documentation
| Component | Technology |
|---|---|
| Framework | FastAPI 0.104+ |
| Database | PostgreSQL (Neon Serverless) |
| ORM | SQLAlchemy 2.0+ |
| Authentication | JWT (python-jose) |
| Password Hashing | Argon2 (passlib) |
| Server | Uvicorn |
| Language | Python 3.10+ |
Project-FastAPI-Blog/
βββ app/
β βββ api/
β β βββ deps.py # Dependency injection (DB, Auth)
β β βββ users_routes.py # User endpoints
β β βββ blogs_routes.py # Blog endpoints
β βββ core/
β β βββ config.py # Configuration & environment variables
β β βββ exceptions.py # Custom exception classes
β β βββ logger.py # JSON logging setup
β β βββ secure.py # Authentication & password hashing
β β βββ validators.py # Input validation
β βββ database/
β β βββ base.py # SQLAlchemy base model
β β βββ session.py # Database engine & session
β βββ models/
β β βββ users_and_blog.py # User & Blog database models
β βββ schemas/
β βββ users.py # User Pydantic schemas
β βββ blog.py # Blog Pydantic schemas
βββ main.py # FastAPI application entry point
βββ .env # Environment variables (not in git)
βββ .env.example # Example environment file
βββ .gitignore # Git ignore rules
βββ requirements.txt # Python dependencies
- Python 3.10 or higher
- PostgreSQL database (or Neon serverless account)
- pip package manager
- Clone the repository:
git clone https://github.com/yourusername/Project-FastAPI-Blog.git
cd Project-FastAPI-Blog- Create virtual environment:
python -m venv .venv
.venv\Scripts\Activate.ps1 # Windows PowerShell
# or
source .venv/bin/activate # Linux/Mac- Install dependencies:
pip install -r requirements.txt- Setup environment variables:
cp .env.example .env
# Edit .env with your Neon PostgreSQL connection string and secrets- Run the application:
uvicorn main:app --reloadThe API will be available at: http://127.0.0.1:8000
Create a .env file in the project root:
# Neon PostgreSQL Connection
DATABASE_URL=postgresql://dbname:your_password@ep-xxxx.region.aws.neon.tech/neondb?sslmode=require
# JWT Security
SECRET_KEY=your-super-secret-key-change-in-production
ALGORITHM=HS256
# Token Expiration (in minutes)
ACCESS_TOKEN_EXPIRE_MINUTES=30
REFRESH_TOKEN_EXPIRE_MINUTES=10080Get your Neon connection string:
- Visit Neon Console
- Select your project
- Click "Connection String"
- Select "psycopg2" driver
- Copy the full connection string
- URL: http://127.0.0.1:8000/docs
- Click "Try it out" to test endpoints directly
curl http://127.0.0.1:8000/healthPOST /api/users/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "secure_password",
"role": "user"
}POST /api/users/login
Content-Type: application/x-www-form-urlencoded
username=user@example.com&password=secure_passwordResponse:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}GET /api/users/me
Authorization: Bearer {access_token}POST /api/blogs/
Authorization: Bearer {access_token}
Content-Type: application/json
{
"title": "My First Blog Post",
"slug": "my-first-blog-post",
"content": "This is the content of my blog post..."
}GET /api/blogs/GET /api/blogs/{blog_id}PUT /api/blogs/{blog_id}
Authorization: Bearer {access_token}
Content-Type: application/json
{
"title": "Updated Title",
"content": "Updated content..."
}DELETE /api/blogs/{blog_id}
Authorization: Bearer {access_token}The API uses JWT (JSON Web Tokens) for authentication:
- User registers and logs in
- Server returns
access_tokenandtoken_type - Client includes token in Authorization header:
Bearer {token} - Server validates token and returns protected resources
Token includes:
- User ID
- Expiration time (30 minutes default)
- Signature verification
CREATE TABLE blog_users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL,
role VARCHAR(255) DEFAULT 'user',
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);CREATE TABLE users_blogs (
id SERIAL PRIMARY KEY,
title VARCHAR NOT NULL,
slug VARCHAR UNIQUE NOT NULL,
content TEXT NOT NULL,
author_id INTEGER FOREIGN KEY REFERENCES blog_users(id),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);All requests and errors are logged in JSON format:
{
"timestamp": "2026-06-07T10:30:45.123456",
"level": "INFO",
"message": "Incoming request: POST /api/users/register",
"module": "main",
"funcName": "log_requests",
"lineno": 65
}Logs are stored in:
-
Console: Real-time output
-
File:
logs/{YYYY-MM-DD}.log(rotated daily) -
Heroku: Add
Procfilewith gunicorn command -
Railway: Connect GitHub repo directly
-
Render: Use Docker or Python buildpack
-
AWS/Azure: Use EC2/App Service with gunicorn
β Implemented:
- Password hashing with Argon2
- JWT token-based authentication
- Refresh token support
- CORS configuration
- Error handling without exposing internals
- Environment variable protection
- Use strong
SECRET_KEY(generate withopenssl rand -hex 32) - Enable HTTPS/SSL
- Restrict CORS origins (replace
*with specific domains) - Set secure database user with minimal permissions
- Enable database encryption
- Implement rate limiting
- Add request validation & sanitization
- Set up monitoring & alerting
fastapi==0.104.1
uvicorn==0.24.0
sqlalchemy==2.0.23
psycopg2-binary==2.9.9
passlib[argon2]==1.7.4
python-jose[cryptography]==3.3.0
pydantic-settings==2.1.0
python-dotenv==1.0.0
Install all: pip install -r requirements.txt
- Issue:
password authentication failed - Solution: Verify
DATABASE_URLin.envwith correct credentials from Neon Console
- Issue:
ModuleNotFoundError: No module named 'app' - Solution: Run from project root and ensure virtual environment is activated
- Issue:
OSError: Address already in use - Solution: Change port:
uvicorn main:app --port 8001
- Issue: Environment variables not recognized
- Solution: Restart the application after updating
.env
- Fork the repository
- Create a feature branch:
git checkout -b feature/new-feature - Commit changes:
git commit -m "Add new feature" - Push to branch:
git push origin feature/new-feature - Submit a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
For issues, questions, or suggestions:
- Open an Issue
- Contact: letsrock10_vicky@live.com
Happy Coding and practice! π
Made with β€οΈ using FastAPI and PostgreSQL