Flask blueprints: modular routing without a microservice
Blueprints group related routes, templates, and static files into a self-contained module that registers onto the main Flask app. They give you modularity without splitting the deployment.
A Flask blueprint is a way to organize a chunk of your app — a set of routes, templates, and static files — into its own module that the main app then registers. The runtime is still one process, one Flask app, one deployment. The split is purely organizational.
Why blueprints over plain routes
In a small app, defining routes directly on the Flask() instance is fine. Once you have more than a handful, three problems show up:
- One huge
app.pywith every route, harder to navigate. - Circular imports when route files need shared models or extensions.
- No URL prefix grouping — you have to spell out
/admin/...in front of every admin route.
Blueprints solve all three. Each blueprint is a Blueprint() object that collects routes the same way Flask() does, then gets attached at registration time.
Minimal example
# blueprints/blog.py
from flask import Blueprint, render_template
blog_bp = Blueprint("blog", __name__, url_prefix="/blog")
@blog_bp.route("/")
def index():
return render_template("blog/index.html")
@blog_bp.route("/<slug>")
def post(slug):
return render_template("blog/post.html", slug=slug)
# app.py
from flask import Flask
from blueprints.blog import blog_bp
def create_app():
app = Flask(__name__)
app.register_blueprint(blog_bp)
return app
Routes are now /blog/ and /blog/<slug> — the prefix is applied once at registration.
Useful blueprint features
url_prefix— applied to every route in the blueprint.template_folder/static_folder— each blueprint can carry its own templates and static assets.url_for("blog.post", slug="hello")— blueprint name is part of the endpoint, sourl_forcalls stay namespaced and can't collide.- Per-blueprint
before_request,after_request,errorhandler— scope middleware to just the routes that need it (e.g., admin auth checks only on the admin blueprint).
When NOT to use a blueprint
- A single route that doesn't fit any group — leave it on the main app.
- You actually need an independent deployment with its own scaling, secrets, or release cadence — that's a separate service, not a blueprint.
Common pitfall
If two blueprints define a route with the same endpoint name (the function name, not the URL), the second registration silently overrides the first. Naming the function with a verb specific to the blueprint (blog_index, not index) avoids accidental collisions.