Scaffold a Flask‑secure boilerplate API.
Project description
Step-by-Step Tutorial: Production‑Ready Flask API Boilerplate
This guide will walk you through creating a production-ready Flask REST API boilerplate with integrated security, multi-database compatibility, and a suite of endpoints demonstrating common flows (CRUD, authentication, health checks). You can clone and run immediately after installation.
- Project Overview & Goals
Production‑ready: Configuration for environments, logging, error handling.
Security: JWT authentication, CORS, input validation.
Database‑agnostic: Works with SQLite, PostgreSQL, MySQL, SQL Server, etc. via an environment variable.
Modular structure: Blueprints for separation of concerns.
Example endpoints: Health check, User signup/signin, CRUD for a sample resource (Item).
- Directory Structure
flask_api_boilerplate/ ├── .env # Environment variables ├── requirements.txt # Python dependencies ├── run.py # Entry point ├── config.py # Configuration classes ├── gunicorn.conf.py # Gunicorn production settings ├── app/ # Application package │ ├── init.py # App factory │ ├── extensions.py # Initialize extensions (SQLAlchemy, Migrate, JWT, CORS) │ ├── models.py # DB models │ ├── schemas.py # Marshmallow schemas │ ├── blueprints/ # All blueprints │ │ ├── auth/ # Authentication │ │ │ ├── init.py │ │ │ ├── views.py │ │ │ └── serializers.py │ │ ├── users/ # Protected user endpoints │ │ │ ├── init.py │ │ │ └── views.py │ │ └── items/ # CRUD sample resource │ │ ├── init.py │ │ └── views.py │ └── utils.py # Helpers (error handlers, validators) └── logs/ # Log files
- Requirements & Environment
Python & Virtualenv
python3 -m venv venv source venv/bin/activate
requirements.txt
Flask>=2.3 Flask-SQLAlchemy Flask-Migrate Flask-JWT-Extended Flask-Cors python-dotenv marshmallow marshmallow-sqlalchemy gunicorn
Install dependencies
pip install -r requirements.txt
Environment Variables (.env file)
FLASK_ENV=production SECRET_KEY=replace-with-secure-key JWT_SECRET_KEY=replace-with-secure-key DATABASE_URL=sqlite:///data.db # or postgresql://user:pass@host/db
- Configuration (config.py)
import os from dotenv import load_dotenv
load_dotenv() # read .env
class BaseConfig: SECRET_KEY = os.getenv('SECRET_KEY') JWT_SECRET_KEY = os.getenv('JWT_SECRET_KEY') SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL') SQLALCHEMY_TRACK_MODIFICATIONS = False PROPAGATE_EXCEPTIONS = True
class ProductionConfig(BaseConfig): DEBUG = False LOG_LEVEL = 'INFO'
class DevelopmentConfig(BaseConfig): DEBUG = True LOG_LEVEL = 'DEBUG'
config = { 'production': ProductionConfig, 'development': DevelopmentConfig, }
- Extensions (app/extensions.py)
from flask_sqlalchemy import SQLAlchemy from flask_migrate import Migrate from flask_jwt_extended import JWTManager from flask_cors import CORS
Initialize extensions
db = SQLAlchemy() migrate = Migrate() jwt = JWTManager() cors = CORS()
- App Factory (app/init.py)
from flask import Flask, jsonify from .extensions import db, migrate, jwt, cors from .config import config from .blueprints.auth.views import auth_bp from .blueprints.users.views import users_bp from .blueprints.items.views import items_bp
def create_app(env=None): app = Flask(name) env = env or os.getenv('FLASK_ENV', 'development') app.config.from_object(config[env])
# Initialize extensions
db.init_app(app)
migrate.init_app(app, db)
jwt.init_app(app)
cors.init_app(app)
# Register blueprints
app.register_blueprint(auth_bp, url_prefix='/auth')
app.register_blueprint(users_bp, url_prefix='/users')
app.register_blueprint(items_bp, url_prefix='/items')
# Health check
@app.route('/health', methods=['GET'])
def health():
return jsonify({'status': 'ok'}), 200
return app
- Models & Schemas (app/models.py & app/schemas.py)
from .extensions import db
class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) password_hash = db.Column(db.String(128), nullable=False)
class Item(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(120), nullable=False) description = db.Column(db.String(255))
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema from .models import User, Item
class UserSchema(SQLAlchemyAutoSchema): class Meta: model = User load_instance = True exclude = ('password_hash',)
class ItemSchema(SQLAlchemyAutoSchema): class Meta: model = Item load_instance = True
- Authentication Blueprint (app/blueprints/auth/views.py)
from flask import Blueprint, request, jsonify from werkzeug.security import generate_password_hash, check_password_hash from flask_jwt_extended import create_access_token from ...extensions import db from ...models import User
auth_bp = Blueprint('auth', name)
@auth_bp.route('/register', methods=['POST']) def register(): data = request.get_json() if User.query.filter_by(username=data['username']).first(): return jsonify({'message': 'User exists'}), 409 user = User( username=data['username'], password_hash=generate_password_hash(data['password']) ) db.session.add(user) db.session.commit() return jsonify({'id': user.id, 'username': user.username}), 201
@auth_bp.route('/login', methods=['POST']) def login(): data = request.get_json() user = User.query.filter_by(username=data['username']).first() if not user or not check_password_hash(user.password_hash, data['password']): return jsonify({'message': 'Bad credentials'}), 401 token = create_access_token({'id': user.id}) return jsonify({'token': token}), 200
- Protected User Endpoints (app/blueprints/users/views.py)
from flask import Blueprint, jsonify from flask_jwt_extended import jwt_required, get_jwt_identity from ...models import User from ...schemas import UserSchema
users_bp = Blueprint('users', name) user_schema = UserSchema()
@users_bp.route('/profile', methods=['GET']) @jwt_required() def profile(): user_id = get_jwt_identity()['id'] user = User.query.get_or_404(user_id) return user_schema.jsonify(user), 200
- CRUD Sample Resource (app/blueprints/items/views.py)
from flask import Blueprint, request from flask_jwt_extended import jwt_required from ...extensions import db from ...models import Item from ...schemas import ItemSchema
items_bp = Blueprint('items', name) item_schema = ItemSchema() items_schema = ItemSchema(many=True)
@items_bp.route('/', methods=['GET']) def list_items(): items = Item.query.all() return items_schema.jsonify(items), 200
@items_bp.route('/', methods=['POST']) @jwt_required() def create_item(): data = request.get_json() item = item_schema.load(data, session=db.session) db.session.add(item) db.session.commit() return item_schema.jsonify(item), 201
@items_bp.route('/int:item_id', methods=['PUT']) @jwt_required() def update_item(item_id): item = Item.query.get_or_404(item_id) data = request.get_json() item.name = data.get('name', item.name) item.description = data.get('description', item.description) db.session.commit() return item_schema.jsonify(item), 200
@items_bp.route('/int:item_id', methods=['DELETE']) @jwt_required() def delete_item(item_id): item = Item.query.get_or_404(item_id) db.session.delete(item) db.session.commit() return '', 204
- Entry Point (run.py)
from app import create_app
app = create_app()
if name == 'main': app.run(host='0.0.0.0', port=5000)
- Gunicorn Configuration (gunicorn.conf.py)
gunicorn.conf.py
bind = '0.0.0.0:8000' workers = 4 accesslog = 'logs/access.log' errorlog = 'logs/error.log' loglevel = 'info'
- Logging & Error Handling
Flask’s built‑in logger will capture errors; logs write to logs/ via Gunicorn.
Customize error handlers in app/utils.py as needed.
- Running the App
Migrate database
export FLASK_ENV=development flask db init flask db migrate flask db upgrade
Run locally
python run.py
Production with Gunicorn
gunicorn -c gunicorn.conf.py run:app
- README.md (Usage Instructions)
Flask API Boilerplate
This is a production-ready, secure, database-agnostic Flask REST API boilerplate.
🚀 Features
- JWT Authentication
- Modular Blueprint Structure
- Compatible with SQLite, PostgreSQL, MySQL, SQL Server
- CRUD Example + Auth + Profile + Healthcheck
- Ready for Production (Gunicorn, Logging, Environment Configs)
🧰 How to Use
1. Clone the repository
git clone <your-repo-url>
cd flask_api_boilerplate
2. Setup your environment
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
cp .env.example .env
3. Configure your .env
Set the appropriate DATABASE_URL, SECRET_KEY, and JWT_SECRET_KEY.
4. Migrate and Run
flask db init
flask db migrate
flask db upgrade
python run.py # or use Gunicorn in production
5. Available Endpoints
Method
Endpoint
Description
GET
/health
Health Check
POST
/auth/register
Register New User
POST
/auth/login
Login & Get JWT Token
GET
/users/profile
Protected User Info
GET
/items/
List Items
POST
/items/
Create Item
PUT
/items/
Update Item
DELETE
/items/
Delete Item
🧩 How to Modify for Your Use
Add more blueprints inside app/blueprints/
Add more models in app/models.py
Use .env to switch databases
Extend auth logic or add roles with flask-jwt-extended
Add custom error handling inside app/utils.py
🛡️ Security Tips
Always keep SECRET_KEY and JWT_SECRET_KEY safe
Enable HTTPS in production
Rotate tokens if needed
Sanitize all inputs if working with raw SQL
🏁 Ready to Deploy
Use Gunicorn:
gunicorn -c gunicorn.conf.py run:app
✅ Contribute or Extend
Fork and make your custom app on top of this base!
---
You now have a fully functional, secure, production-ready Flask API boilerplate compatible with multiple databases.
Feel free to extend with more blueprints, middleware, and custom error handlers as your project grows!
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flasksecforge-0.1.0.tar.gz.
File metadata
- Download URL: flasksecforge-0.1.0.tar.gz
- Upload date:
- Size: 11.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
291eb8c42612382c3403fe9c95367899524bd8fd22a001ff96d466da8e95a954
|
|
| MD5 |
23498c5862f47252466bd2411deb1bb6
|
|
| BLAKE2b-256 |
86e5305518cf9ba65a7ba8f4b695a741b402f4c63eb6b07ecefbf826a484807c
|
File details
Details for the file flasksecforge-0.1.0-py3-none-any.whl.
File metadata
- Download URL: flasksecforge-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
41a5a62d37c811a238eaddfe03785112c1cb56fafe6531c023362b4968ab7d46
|
|
| MD5 |
a3e0508b6e6c71094a5fbf8de6f9cf33
|
|
| BLAKE2b-256 |
c5a5bb3c854d9f62a1847bf49a749f8b78993b3165be2fee5929c2b8367e0f4a
|