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.1.tar.gz (12.0 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.1-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

Details for the file flasksecforge-0.1.1.tar.gz.

File metadata

  • Download URL: flasksecforge-0.1.1.tar.gz
  • Upload date:
  • Size: 12.0 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.1.tar.gz
Algorithm Hash digest
SHA256 7ef5fa7bb2f31db64f679322cdf6a6a05aaff9727b9e9ae84708688fbb7dd4b8
MD5 c1d533011e3deacf457f5da445ffa765
BLAKE2b-256 48b8eac8dcbd8676ab238b1fd780a149d90541fc9f17478a66f019354e6dfd1a

See more details on using hashes here.

File details

Details for the file flasksecforge-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: flasksecforge-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 18.0 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 119acac1fa453838b5f35a7b618cd6f64f4ef8dafc7c5d23d1739051a4bba37c
MD5 a3083446c3b01340c0d16464af8977e1
BLAKE2b-256 8192c6877a78fe09a704237862825025ef4cbbb5f34ab01a6de7411a2e11f6d4

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