Blueprints
Blueprints define HTTP routes and serve frontend assets. Every feature creates exactly one.
Table of contents
What they do
A blueprint groups all routes, templates, and static assets for a feature into one unit that Flask can register at startup. SPLENT’s create_blueprint adds automatic template resolution and asset routing on top.
Creating a blueprint
In your feature’s __init__.py:
# splent_feature_notes/__init__.py
from splent_framework.blueprints.base_blueprint import create_blueprint
from splent_framework.services.service_locator import register_service
from splent_io.splent_feature_notes.services import NotesService
notes_bp = create_blueprint(__name__)
def init_feature(app):
register_service(app, "NotesService", NotesService)
def inject_context_vars(app):
return {}
create_blueprint(__name__) infers the short name from the module path:
splent_io.splent_feature_notes→notessplent_io.splent_feature_notes_tags→notes_tags
Defining routes
Routes go in routes.py. They handle HTTP only — parsing requests, rendering templates, flash messages, redirects. All logic is delegated to services:
# splent_feature_notes/routes.py
from flask import render_template, request, redirect, url_for, flash
from flask_login import login_required, current_user
from splent_io.splent_feature_notes import notes_bp
from splent_framework.services.service_locator import service_proxy
notes_service = service_proxy("NotesService")
@notes_bp.route("/notes/", methods=["GET"])
@login_required
def index():
notes = notes_service.get_by_user(current_user.id)
return render_template("notes/index.html", notes=notes)
@notes_bp.route("/notes/create", methods=["GET", "POST"])
@login_required
def create():
if request.method == "POST":
title = request.form.get("title", "").strip()
content = request.form.get("content", "").strip()
if not title:
flash("Title is required.", "danger")
return render_template("notes/create.html")
notes_service.create(user_id=current_user.id, title=title, content=content)
flash("Note created.", "success")
return redirect(url_for("notes.index"))
return render_template("notes/create.html")
Automatic features
Template resolution
If you don’t specify template_folder, the blueprint resolves it to <package_dir>/templates/ automatically.
Asset routes
Three routes are registered automatically:
| Route | Serves from |
|---|---|
/<name>/js/<filename> |
assets/js/ |
/<name>/css/<filename> |
assets/css/ |
/<name>/dist/<filename> |
assets/dist/ |
Assets are served with path traversal protection.
Package resolution
The blueprint resolves its physical directory via Python’s module system, so it works whether the feature is installed as editable or as a pinned snapshot.
MANIFEST.in
To include compiled assets in the package distribution:
recursive-include src/<org>/<feature>/assets/dist *.js *.css *.map
See also
- Services — the layer routes delegate to
- Feature anatomy — file structure of a feature