Skip to main content

starlette-hot-reload

Hot reload for Starlette templates and static files

PyPI - Version PyPI - Python Version PyPI - License

Overview

starlette-hot-reload reloads the browser when your Starlette templates or static assets change. It injects a small client script into HTML responses and uses Server-Sent Events (SSE) to notify the browser about changes.

Demo

Quick Start

Install the package:

uv add starlette-hot-reload
# or
pip install starlette-hot-reload

Enable it in your app lifespan:

from contextlib import asynccontextmanager
from starlette.applications import Starlette
from starlette_hot_reload import hot_reload

@asynccontextmanager
async def lifespan(app: Starlette):
    async with hot_reload(app=app, watch_dirs=["templates", "static"]):
        yield

app = Starlette(
    debug=True,
    lifespan=lifespan,
)

Run your app:

uvicorn main:app

What You Get

  • Reloads the browser when watched files change.
  • Injects the client script into HTML responses automatically.
  • Uses SSE, no websocket.
  • Composes with Starlette lifespan context managers.
  • Adds no extra runtime dependency beyond Starlette.

Basic Usage

Hot reload only runs when debug=True.

app = Starlette(debug=True)

Watch specific directories:

@asynccontextmanager
async def lifespan(app: Starlette):
    async with hot_reload(
        app=app,
        watch_dirs=["templates", "static", "assets"],
    ):
        yield

Use a custom SSE endpoint:

async with hot_reload(
    app=app,
    watch_dirs=["templates", "static"],
    events_path="/custom-events-path",
):
    ...

Tune filesystem polling:

async with hot_reload(
    app=app,
    watch_dirs=["templates", "static"],
    poll_interval=0.25,
):
    ...

Compose it with other lifespan resources using AsyncExitStack:

from contextlib import AsyncExitStack, asynccontextmanager

@asynccontextmanager
async def lifespan(app: Starlette):
    async with AsyncExitStack() as stack:
        await stack.enter_async_context(
            hot_reload(app=app, watch_dirs=["templates", "static"])
        )
        yield

How It Works

When you request an HTML page, the middleware injects a small client script into the response body. That script opens an SSE connection to the app.

The file watcher polls the directories you configured. When a file changes:

  • Watched changes trigger a full page reload.

This package complements server reload tools such as uvicorn --reload. It does not restart your Python process.

Limits

  • Hot reload is disabled when debug=False.
  • The watcher uses polling, not native OS file notifications.
  • Python code changes reload the browser page, but they do not reload server state or restart the app process.
  • Script injection targets HTML responses. Non-HTML responses are left alone.

Examples

The repository includes example apps under examples/.

examples/basic

This example shows the smallest Starlette setup with:

  • Jinja templates
  • Static files
  • hot_reload() in the app lifespan

Run it from the repository root:

uv run python -m examples.basic.app

Open http://127.0.0.1:3000 and edit files in examples/basic/templates or examples/basic/static.

examples/with_tailwind

This example shows how to compose starlette-hot-reload with starlette-tailwindcss.

It watches the whole example directory so changes to templates, CSS, and built assets all trigger a browser reload.

Run it from the repository root:

uv run python -m examples.with_tailwind.app

Open http://127.0.0.1:3000 and edit files in examples/with_tailwind/.

Debug Logging

If you want watcher and SSE logs during development, enable Python logging:

import logging
import sys

logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s %(levelname)s [%(name)s] %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
    stream=sys.stderr,
)

More Starlette Packages

If you are building server-rendered Starlette apps, these packages fit well with starlette-hot-reload:

License

MIT

Metadata

Release files for starlette-hot-reload 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for starlette-hot-reload 0.3.0
File Size Uploaded Provenance Actions
starlette_hot_reload-0.3.0.tar.gz 9.9 kB Without provenance Details for starlette_hot_reload-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for starlette-hot-reload 0.3.0
File Interpreter ABI Platform Actions
starlette_hot_reload-0.3.0-py3-none-any.whl Python 3 none any Details for starlette_hot_reload-0.3.0-py3-none-any.whl

Total release size: 22.4 kB

Release files / starlette_hot_reload-0.3.0.tar.gz

Download URL starlette_hot_reload-0.3.0.tar.gz
Size 9.9 kB
Tags Source
SHA-256 checksum
How to use checksums
22e8135a3bfa772aa7e78fb9e58d55dd27449ceed9fa3eb3723c09db701d523e
BLAKE2b-256 checksum
How to use checksums
579fee3ea1f006a64d2ec1a7315573d57fdda01815bb3ba2c7d2a437b0426260
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.4 {"installer":{"name":"uv","version":"0.11.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / starlette_hot_reload-0.3.0-py3-none-any.whl

Download URL starlette_hot_reload-0.3.0-py3-none-any.whl
Size 12.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b4b5cfb8a51d12b4186da0f2ef5820ed0b2a4afdc1d13673186eb37752c78172
BLAKE2b-256 checksum
How to use checksums
cf10dd345d1f5ee69a4369eaca762c43b8e54703ec73aed64824da960976dd67
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.4 {"installer":{"name":"uv","version":"0.11.4","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for starlette-hot-reload 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page