Skip to main content

Serving Static Files and Resources

Blueprints allow you to organize your application into distinct components, each with its own static files and internal resources. This is particularly useful for modular applications where a specific feature (like an admin panel or a user dashboard) needs to bundle its own CSS, JavaScript, or data files.

Configuring a Blueprint Static Folder

To serve static files from a blueprint, specify the static_folder argument when initializing the Blueprint. By default, Flask will serve these files at the blueprint's url_prefix followed by /static.

from flask import Blueprint

# Files in 'my_package/static/' will be served at '/my_feature/static/'
bp = Blueprint(
"my_feature",
__name__,
url_prefix="/my_feature",
static_folder="static"
)

If you want to change the URL path where static files are served, use the static_url_path parameter:

bp = Blueprint(
"assets",
__name__,
static_folder="static",
static_url_path="/assets"
)

Accessing Static URLs in Templates

When a blueprint has a static folder, you can generate URLs for its files using the special static endpoint prefixed with the blueprint's name:

<link rel="stylesheet" href="{{ url_for('my_feature.static', filename='style.css') }}">

Accessing Internal Package Resources

If you need to read a file located within your blueprint's package (such as a SQL schema or a configuration file) programmatically, use the open_resource method. This method ensures the path is correctly resolved relative to the blueprint's root_path.

# In src/flask/blueprints.py, open_resource is defined to read files
# relative to the blueprint's directory.

def init_db(bp):
with bp.open_resource("schema.sql") as f:
schema = f.read().decode("utf-8")
# ... execute schema ...

open_resource supports the following modes:

  • "r" or "rt": Open for reading in text mode (default encoding is UTF-8).
  • "rb": Open for reading in binary mode.

Serving Static Files Manually

In some cases, you may want to serve a static file from a custom view function rather than the default route. You can use the send_static_file method for this purpose.

@bp.route("/logo")
def serve_logo():
# This serves 'logo.png' from the blueprint's static_folder
return bp.send_static_file("logo.png")

Customizing Cache Headers

You can control how long browsers should cache static files by overriding the get_send_file_max_age method in a subclass of Blueprint. By default, it uses the SEND_FILE_MAX_AGE_DEFAULT configuration from the application.

class MyBlueprint(Blueprint):
def get_send_file_max_age(self, filename):
if filename.endswith(".js"):
return 3600 # Cache JavaScript for 1 hour
return super().get_send_file_max_age(filename)

bp = MyBlueprint("custom", __name__, static_folder="static")

Troubleshooting

Static Files Not Found

If your blueprint's static files are returning 404 errors, check the following:

  1. URL Prefix Conflicts: If your blueprint does not have a url_prefix, its static route might conflict with the main application's static route. Always provide a url_prefix or a unique static_url_path for blueprints with static folders.
  2. Missing Folder: Ensure the directory specified in static_folder actually exists relative to the file where the Blueprint is defined.
  3. Initialization: The static_folder must be set during initialization. You cannot serve files via send_static_file if static_folder was not provided to the constructor.

Resource Access Errors

open_resource is strictly for reading. Attempting to open a file with write modes (like "w" or "a") will raise a ValueError.

# This will raise ValueError: Resources can only be opened for reading.
with bp.open_resource("data.json", mode="w") as f:
f.write("{}")