Serving HTML and Static files

FastAPI is not only for APIs; it also provides robust support for serving HTML content and static files, which is essential for web applications that require a frontend. Below, we'll cover how to serve HTML templates and static files like CSS, JavaScript, and images.

Serving HTML Templates

FastAPI uses Jinja2, a fast, secure, and designer-friendly templating engine for Python, to render HTML templates.

Step-by-Step Guide to Serving HTML

  1. Install Jinja2 and aiofiles
    First, you need to install Jinja2 and aiofiles (an asynchronous file handling library):
    pip install jinja2 aiofiles
    
  2. Project Structure
    Create a directory structure to hold your templates and static files:
    fastapi_project/
    │
    ├── main.py
    ├── templates/
    │   └── index.html
    ├── static/
    │   ├── css/
    │   │   └── styles.css
    │   └── js/
    │       └── script.js
    └── requirements.txt
    
  3. Setting Up Template Directory
    Configure FastAPI to use the templates directory for Jinja2 templates.
    # main.py
    from fastapi import FastAPI, Request
    from fastapi.templating import Jinja2Templates
    from fastapi.staticfiles import StaticFiles
    
    app = FastAPI()
    
    # Mount the static files directory
    app.mount("/static", StaticFiles(directory="static"), name="static")
    
    # Define the templates directory
    templates = Jinja2Templates(directory="templates")
    
    @app.get("/")
    async def read_root(request: Request):
        return templates.TemplateResponse("index.html", {"request": request, "title": "Home"})
    
    • app.mount is used to serve static files. The directory parameter points to the static folder, and the files will be accessible under the /static URL path.
    • Jinja2Templates is configured to look for templates in the templates directory.
    • templates.TemplateResponse is used to render index.html with the provided context (like title).
  4. Creating a Basic HTML Template
    In the templates directory, create an index.html file:
    <!-- templates/index.html -->
    <!DOCTYPE html>
    <html>
    <head>
        <title>{{ title }}</title>
        <link rel="stylesheet" type="text/css" href="/static/css/styles.css">
    </head>
    <body>
        <h1>{{ title }}</h1>
        <p>Welcome to FastAPI with HTML templates!</p>
        <script src="/static/js/script.js"></script>
    </body>
    </html>
    
    • This template uses Jinja2 syntax for templating.
    • It includes a link to a CSS file and a JavaScript file served from the static directory.
  5. Running the Application
    Start your FastAPI server:
    uvicorn main:app --reload
    

    Navigate to http://127.0.0.1:8000 in your browser to see the rendered HTML.

Serving Static Files

Serving static files is straightforward with FastAPI. You can serve CSS, JavaScript, images, or any other static assets.

Step-by-Step Guide to Serving Static Files

  1. Mount the Static Directory
    As shown above, use app.mount to serve the static directory:
    app.mount("/static", StaticFiles(directory="static"), name="static")
    
    • This makes all files in the static directory accessible under the /static URL path.
  2. Accessing Static Files in HTML
    Reference static files in your HTML templates using their paths relative to the /static URL path:
    <link rel="stylesheet" type="text/css" href="/static/css/styles.css">
    <script src="/static/js/script.js"></script>
    
    • The above example links a CSS file and a JavaScript file.
  3. Example Static Files
    Create some example static files:
    /* static/css/styles.css */
    body {
        font-family: Arial, sans-serif;
        background-color: #f0f0f0;
        color: #333;
    }
    
    h1 {
        color: #007bff;
    }
    
    // static/js/script.js
    console.log("FastAPI with static files!");
    

    These files can be used to style your HTML and add interactivity via JavaScript.

Example Project

Here's a complete example of a FastAPI project that serves HTML and static files:

Project Structure

fastapi_project/
│
├── main.py
├── templates/
│   └── index.html
├── static/
│   ├── css/
│   │   └── styles.css
│   └── js/
│       └── script.js
└── requirements.txt

main.py

from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles

app = FastAPI()

# Mount static files directory
app.mount("/static", StaticFiles(directory="static"), name="static")

# Define the templates directory
templates = Jinja2Templates(directory="templates")

@app.get("/")
async def read_root(request: Request):
    return templates.TemplateResponse("index.html", {"request": request, "title": "Home"})

templates/index.html

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
    <link rel="stylesheet" type="text/css" href="/static/css/styles.css">
</head>
<body>
    <h1>{{ title }}</h1>
    <p>Welcome to FastAPI with HTML templates!</p>
    <script src="/static/js/script.js"></script>
</body>
</html>

static/css/styles.css

body {
    font-family: Arial, sans-serif;
    background-color: #f0f0f0;
    color: #333;
}

h1 {
    color: #007bff;
}

static/js/script.js

console.log("FastAPI with static files!");

Conclusion

By following these steps, you can serve both HTML content and static files using FastAPI. This allows you to build full-featured web applications with a backend API and a frontend served by the same framework.