Skip to main content

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.

  1. 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).

  1. 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

  1. 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

  1. 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, }

  1. 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()

  1. 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
  1. 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

  1. 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

  1. 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

  1. 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

  1. Entry Point (run.py)

from app import create_app

app = create_app()

if name == 'main': app.run(host='0.0.0.0', port=5000)

  1. 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'

  1. 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.

  1. 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

  1. 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

flasksecforge-0.1.0.tar.gz (11.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flasksecforge-0.1.0-py3-none-any.whl (17.7 kB view details)

Uploaded Python 3

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

Hashes for flasksecforge-0.1.0.tar.gz
Algorithm Hash digest
SHA256 291eb8c42612382c3403fe9c95367899524bd8fd22a001ff96d466da8e95a954
MD5 23498c5862f47252466bd2411deb1bb6
BLAKE2b-256 86e5305518cf9ba65a7ba8f4b695a741b402f4c63eb6b07ecefbf826a484807c

See more details on using hashes here.

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

Hashes for flasksecforge-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 41a5a62d37c811a238eaddfe03785112c1cb56fafe6531c023362b4968ab7d46
MD5 a3e0508b6e6c71094a5fbf8de6f9cf33
BLAKE2b-256 c5a5bb3c854d9f62a1847bf49a749f8b78993b3165be2fee5929c2b8367e0f4a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page