Skilllibrary flask
Guides Flask application development: application factory creation, Blueprint organization, extension wiring (SQLAlchemy, Migrate, Login, WTF), request/app context handling, error handler registration, configuration management, Jinja2 templating, and WSGI deployment with gunicorn or waitress.
git clone https://github.com/merceralex397-collab/skilllibrary
T=$(mktemp -d) && git clone --depth=1 https://github.com/merceralex397-collab/skilllibrary "$T" && mkdir -p ~/.claude/skills && cp -r "$T/09-backend-api-and-data/flask" ~/.claude/skills/merceralex397-collab-skilllibrary-flask && rm -rf "$T"
09-backend-api-and-data/flask/SKILL.mdPurpose
Guides the design and implementation of Flask web applications—from project scaffolding with the application factory pattern through Blueprint decomposition, extension initialization, request lifecycle management, and production WSGI deployment. Ensures Flask-specific idioms are applied correctly so that context handling, configuration layering, and error propagation follow established Flask conventions.
When to use this skill
Use this skill when:
- creating a new Flask application or adding routes/blueprints to an existing one
- wiring Flask extensions (Flask-SQLAlchemy, Flask-Migrate, Flask-Login, Flask-WTF, Flask-CORS)
- working with Flask's request context, application context, or the
objectg - registering error handlers, before/after request hooks, or teardown callbacks
- configuring Flask for multiple environments (dev, test, staging, production)
- writing tests using
ortest_client()test_request_context() - setting up WSGI deployment with gunicorn, waitress, or similar servers
- rendering templates with Jinja2 or building Flask CLI commands
Do not use this skill when
- the project uses FastAPI or another ASGI framework—prefer
skillfastapi - the task is general Python project structure with no Flask dependency—prefer
skillpython - the task is purely frontend HTML/CSS/JS with no server logic
- the project is a Django application
Operating procedure
- Identify the app entry point. Confirm the project uses an application factory (
) or determine whether to introduce one. Check for acreate_app()
orwsgi.py
that calls the factory.app.py - Map the Blueprint structure. Identify existing blueprints in the project. For new features, determine the correct blueprint or whether a new one is needed. Each blueprint should own a URL prefix and group related routes.
- Wire extensions correctly. Extensions must be instantiated at module level (e.g.,
) and initialized inside the factory withdb = SQLAlchemy()
. Never passext.init_app(app)
to the constructor in a factory-based project.app - Handle configuration layering. Use
for defaults,app.config.from_object()
orapp.config.from_envvar()
for environment overrides. Verifyapp.config.from_pyfile()
is set and not hardcoded in production.SECRET_KEY - Register error handlers. Add
,@app.errorhandler(400)
,@app.errorhandler(404)
in the factory or a dedicated errors blueprint. Return JSON or HTML depending on the request's@app.errorhandler(500)
header.Accept - Set up request hooks. Use
for auth checks or request-scoped setup,before_request
for response headers,after_request
for cleanup (closing DB connections, etc.).teardown_appcontext - Write tests. Use
for integration tests andapp.test_client()
for unit tests that need request/app context. Use pytest fixtures to create and configure the test app.app.test_request_context() - Verify deployment readiness. Confirm
,debug=False
is from environment, CSRF protection is active, and the app runs under a WSGI server (notSECRET_KEY
in production).flask run
Decision rules
- Always use the application factory pattern for any project beyond a single-file prototype.
- Initialize extensions with
inside the factory—never at import time with a concrete app instance.init_app(app) - Store request-scoped data on
, not on module-level variables or the session (unless persistence across requests is needed).flask.g - Use
to access the app inside blueprints—never import the app instance directly.current_app - Prefer
over manually constructing error responses in route handlers.abort(status_code) - Keep Jinja2 templates in a
directory co-located with the blueprint or at the app root.templates/ - Use
/flask db migrate
for schema changes—never raw DDL in application code.flask db upgrade - Choose gunicorn (Linux) or waitress (cross-platform) for production; never use the built-in development server.
Output requirements
— factory function, blueprint registration, extension wiringApp Structure
— endpoint, methods, validation, response formatRoute Implementation
— error handler registrations, error response shapeError Handling
— environment-specific config classes, secret managementConfiguration
— pytest commands, test client assertions, deployment checkVerification
References
Read these only when relevant:
— factory, blueprint, extension, and hook patternsreferences/implementation-patterns.md
— pre-deploy and pre-merge verification itemsreferences/validation-checklist.md
— common Flask runtime errors and their fixesreferences/failure-modes.md
Related skills
— general Python project structure, typing, and toolingpython
— alternative Python web framework (ASGI-based)fastapi
— SQLAlchemy model design and query patternsorm-patterns
— database configuration and connection managementpostgresql
— structured logging in Flask applicationsobservability-logging
Anti-patterns
- God factory. Putting all route definitions directly in
instead of using blueprints. This makes the factory unreadable and untestable.create_app() - Import-time app access. Importing
from a module that callsapp
at import time, causing circular imports and context errors.create_app() - Extension double-init. Passing
to an extension constructor AND callingapp
, causing duplicate initialization or configuration conflicts.init_app(app) - Bare
in routes. Catching all exceptions in a route handler, swallowing errors that should propagate to Flask's error handling system.except - Session as cache. Storing large data structures in
, bloating the signed cookie and hitting browser size limits.flask.session
across requests. Assumingg
persists between requests—it is reset on every request.flask.g- Debug mode in production. Leaving
orFLASK_DEBUG=1
in production, exposing the Werkzeug debugger and allowing arbitrary code execution.debug=True - Hardcoded secret key. Committing
and deploying it, making session cookies forgeable.SECRET_KEY = 'dev'
Failure handling
- If an operation fails because code is running outside an application context, wrap it in
or ensure the calling code is within a request or CLI command.with app.app_context(): - If a circular import occurs, move the
into the function body or restructure to usefrom app import db
and late imports.current_app - If CSRF validation fails on a form submission, verify Flask-WTF is initialized and
or{{ form.hidden_tag() }}
is in the template.{{ csrf_token() }} - If tests fail with "Working outside of application context," ensure the test fixture creates an app and pushes the context with
.app.app_context() - If the development server shows "Address already in use," check for zombie processes on the port or use
.flask run --port <alt> - If database migrations fail, check that
is initialized with bothFlask-Migrate
andapp
, and that the migrations directory exists (db
).flask db init