flask-reviewer

physics91's avatarfrom physics91

WHEN: Flask project review, Blueprint structure, extensions, request handlingWHAT: Blueprint organization + Extension patterns + Request/response handling + Configuration + TestingWHEN NOT: FastAPI → fastapi-reviewer, Django → django-reviewer, General Python → python-reviewer

⭐0stars🔀0forks📁View on GitHub🕐Updated Dec 29, 2025

When & Why to Use This Skill

The Flask Reviewer skill is a specialized diagnostic tool designed to audit and optimize Flask web applications. It focuses on enforcing industry best practices, such as the Application Factory pattern and modular Blueprint organization, while identifying critical security risks like hardcoded secrets. By analyzing request handling, extension patterns, and configuration hierarchies, it helps developers transform prototype code into production-ready, scalable, and maintainable Python web services.

Use Cases

  • Refactoring monolithic Flask applications into a modular, Blueprint-based architecture to improve code maintainability and team collaboration.
  • Auditing project configurations to ensure sensitive credentials are moved from source code to environment variables, preventing security leaks.
  • Implementing the Application Factory pattern to resolve circular import issues and enable easier unit testing with different configurations.
  • Enhancing API reliability by identifying missing request validations and suggesting robust schemas using Marshmallow or Pydantic.
  • Standardizing error handling across the application to provide consistent JSON responses and improved logging for production debugging.
nameflask-reviewer
description|
WHENFlask project review, Blueprint structure, extensions, request handling
WHATBlueprint organization + Extension patterns + Request/response handling + Configuration + Testing
WHEN NOTFastAPI → fastapi-reviewer, Django → django-reviewer, General Python → python-reviewer

Flask Reviewer Skill

Purpose

Reviews Flask projects for application structure, extension usage, and best practices.

When to Use

  • Flask project code review
  • Blueprint structure review
  • Extension configuration review
  • Request handling patterns
  • Flask API design

Project Detection

  • flask in requirements.txt/pyproject.toml
  • from flask import Flask imports
  • app.py or __init__.py with Flask()
  • blueprints/ or routes/ directory

Workflow

Step 1: Analyze Project

**Flask**: 3.0+
**Extensions**: Flask-SQLAlchemy, Flask-Login, Flask-WTF
**API**: Flask-RESTful / Flask-RESTX
**Database**: SQLAlchemy
**Template**: Jinja2

Step 2: Select Review Areas

AskUserQuestion:

"Which areas to review?"
Options:
- Full Flask review (recommended)
- Application structure
- Blueprint organization
- Extension configuration
- Security and validation
multiSelect: true

Detection Rules

Application Factory

Check Recommendation Severity
Global app instance Use application factory HIGH
Config in code Use config classes MEDIUM
No extension init Use init_app pattern MEDIUM
Circular imports Use factory + blueprints HIGH
# BAD: Global app instance
# app.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
db = SQLAlchemy(app)  # Tight coupling

# GOOD: Application factory
# app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app(config_name="default"):
    app = Flask(__name__)
    app.config.from_object(config[config_name])

    db.init_app(app)

    from app.routes import main_bp, api_bp
    app.register_blueprint(main_bp)
    app.register_blueprint(api_bp, url_prefix="/api")

    return app

Blueprint Organization

Check Recommendation Severity
All routes in one file Split into blueprints MEDIUM
No URL prefix Add url_prefix to blueprints LOW
Mixed concerns Separate by domain MEDIUM
No init.py exports Export blueprint properly LOW
# GOOD: Blueprint structure
# app/routes/users.py
from flask import Blueprint, request, jsonify

users_bp = Blueprint("users", __name__, url_prefix="/users")

@users_bp.route("/", methods=["GET"])
def list_users():
    return jsonify(users=User.query.all())

@users_bp.route("/<int:user_id>", methods=["GET"])
def get_user(user_id):
    user = User.query.get_or_404(user_id)
    return jsonify(user=user.to_dict())

# app/routes/__init__.py
from app.routes.users import users_bp
from app.routes.products import products_bp

__all__ = ["users_bp", "products_bp"]

Request Handling

Check Recommendation Severity
No input validation Use marshmallow/pydantic HIGH
request.json without check Handle None case MEDIUM
No error handlers Add @app.errorhandler MEDIUM
Sync blocking calls Consider async or Celery MEDIUM
# BAD: No validation
@app.route("/user", methods=["POST"])
def create_user():
    data = request.json  # Could be None!
    user = User(name=data["name"])  # KeyError risk
    return jsonify(user.to_dict())

# GOOD: With validation (marshmallow)
from marshmallow import Schema, fields, validate

class UserSchema(Schema):
    name = fields.Str(required=True, validate=validate.Length(min=1, max=100))
    email = fields.Email(required=True)

user_schema = UserSchema()

@app.route("/user", methods=["POST"])
def create_user():
    data = request.get_json()
    if not data:
        return jsonify(error="No JSON data"), 400

    errors = user_schema.validate(data)
    if errors:
        return jsonify(errors=errors), 400

    user = User(**user_schema.load(data))
    db.session.add(user)
    db.session.commit()
    return jsonify(user=user.to_dict()), 201

Configuration

Check Recommendation Severity
Secrets in code Use environment variables CRITICAL
No config classes Use config hierarchy MEDIUM
DEBUG=True in prod Environment-based config CRITICAL
No instance folder Use instance config LOW
# config.py
import os

class Config:
    SECRET_KEY = os.environ.get("SECRET_KEY") or "dev-key-change-me"
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class DevelopmentConfig(Config):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = os.environ.get("DEV_DATABASE_URL") or \
        "sqlite:///dev.db"

class ProductionConfig(Config):
    DEBUG = False
    SQLALCHEMY_DATABASE_URI = os.environ.get("DATABASE_URL")

    @classmethod
    def init_app(cls, app):
        # Production-specific initialization
        import logging
        from logging.handlers import RotatingFileHandler

        handler = RotatingFileHandler("app.log", maxBytes=10240, backupCount=10)
        handler.setLevel(logging.INFO)
        app.logger.addHandler(handler)

config = {
    "development": DevelopmentConfig,
    "production": ProductionConfig,
    "default": DevelopmentConfig,
}

Error Handling

Check Recommendation Severity
No custom error pages Add error handlers MEDIUM
Exception details in response Hide in production HIGH
No logging Add structured logging MEDIUM
# app/errors.py
from flask import jsonify, render_template

def register_error_handlers(app):
    @app.errorhandler(400)
    def bad_request(error):
        if request_wants_json():
            return jsonify(error="Bad request"), 400
        return render_template("errors/400.html"), 400

    @app.errorhandler(404)
    def not_found(error):
        if request_wants_json():
            return jsonify(error="Not found"), 404
        return render_template("errors/404.html"), 404

    @app.errorhandler(500)
    def internal_error(error):
        db.session.rollback()
        app.logger.error(f"Internal error: {error}")
        if request_wants_json():
            return jsonify(error="Internal server error"), 500
        return render_template("errors/500.html"), 500

def request_wants_json():
    return request.accept_mimetypes.best_match(
        ["application/json", "text/html"]
    ) == "application/json"

Response Template

## Flask Code Review Results

**Project**: [name]
**Flask**: 3.0 | **SQLAlchemy**: 2.0 | **Extensions**: Login, WTF

### Application Structure
| Status | File | Issue |
|--------|------|-------|
| HIGH | app.py | Global app instance - use factory |

### Blueprint Organization
| Status | File | Issue |
|--------|------|-------|
| MEDIUM | routes.py | 50+ routes - split into blueprints |

### Request Handling
| Status | File | Issue |
|--------|------|-------|
| HIGH | views.py:34 | No input validation on POST |

### Configuration
| Status | File | Issue |
|--------|------|-------|
| CRITICAL | config.py | SECRET_KEY hardcoded |

### Recommended Actions
1. [ ] Implement application factory pattern
2. [ ] Split routes into domain blueprints
3. [ ] Add marshmallow validation schemas
4. [ ] Move secrets to environment variables

Best Practices

  1. Factory Pattern: Always use create_app()
  2. Blueprints: Organize by domain/feature
  3. Validation: marshmallow or pydantic
  4. Config: Environment-based hierarchy
  5. Extensions: Use init_app pattern

Integration

  • python-reviewer: General Python patterns
  • security-scanner: Flask security audit
  • api-documenter: API documentation