Skip to main content

Production-oriented unified runtime for FastAPI + Streamlit

Project description

FluxLit (fluxlit)

Documentation Status PyPI version Python versions CI Release License

Production-oriented unified runtime for FastAPI and Streamlit: one public port, one CLI, and a single FluxLit app object for APIs plus UI pages.

Documentation (hosted): https://fluxlit.readthedocs.io/en/stable/

Topic Read the Docs
Quick start Quick start
Architecture & routing Architecture
Config & fluxlit.toml Configuration
CLI (dev, run, doctor, build) CLI
Testing Testing
Python API API reference
Contributing Contributing
Changelog Changelog
Roadmap Roadmap

Also in the repo: Product & architecture plan (source for long-form product context; overview is on Read the Docs under Architecture).


Overview

FluxLit targets teams that want FastAPI for HTTP APIs and Streamlit for interactive UIs without wiring separate ports, ad hoc reverse proxies, and brittle dev scripts. The runtime uses a sidecar model: Streamlit runs in a subprocess; a Starlette ASGI gateway fronts both the API and the UI.


Requirements

  • Python 3.10+
  • Dependencies are declared in pyproject.toml (FastAPI, Uvicorn, Streamlit, Typer, httpx, websockets, etc.).

Install

pip install fluxlit

For local development of FluxLit itself:

git clone https://github.com/eddiethedean/fluxlit.git
cd fluxlit
pip install -e ".[dev]"

Quick start

Create a project (optional):

fluxlit new my-app
cd my-app

Define a FluxLit app (e.g. app.py):

from fluxlit import FluxLit

app = FluxLit(title="Admin Portal")

@app.api.get("/users")
def users():
    return [{"name": "Ada"}]

@app.page("/")
def home(st, client):
    st.title("Dashboard")
    st.write(client.get("/users").json())

Run the unified server (default import path app:app, or target from fluxlit.toml / [tool.fluxlit]):

fluxlit dev
# or explicitly:
fluxlit dev app:app
  • Browser: open the URL shown by Uvicorn (default http://127.0.0.1:8000).
  • API: routes are mounted under /api (e.g. GET /api/users).
  • OpenAPI / docs: http://127.0.0.1:8000/api/docs (Swagger) and /api/openapi.json.
  • Health: http://127.0.0.1:8000/api/healthz (hidden from OpenAPI).

From Streamlit code, ApiClient calls the API using a base URL that includes /api (set automatically as FLUXLIT_INTERNAL_API_BASE when using fluxlit dev / fluxlit run). Use paths like client.get("/users"), not client.get("/api/users").

For typed JSON responses, use ApiClient.get_model / post_model with Pydantic models.


How routing works

Browser
   │
   ▼
┌──────────────────────────────────────┐
│  FluxLit gateway (Uvicorn, one port)  │
├──────────────────────────────────────┤
│  /api/*     → FastAPI (path prefix    │
│               stripped inside the app) │
│  /*         → Streamlit (HTTP + WS    │
│               proxy to subprocess)     │
└──────────────────────────────────────┘

Anything that is not under /api is forwarded to Streamlit (including WebSockets used by Streamlit). Reserve /api for your HTTP API.

Note: the API prefix is configurable via FluxlitSettings.api_mount_path (default /api).


CLI

Command Description
fluxlit dev [target] Development server: Streamlit subprocess + gateway. Default target: CLI arg → fluxlit.toml / pyproject.toml [tool.fluxlit]app:app.
fluxlit run [target] Same stack without auto-reload.
fluxlit doctor [target] Environment checks (import, bind, deps, FLUXLIT_INTERNAL_API_BASE). Exits non-zero on failures unless --warnings-only.
fluxlit build [target] Write a starter Dockerfile and .dockerignore (use --output / -o, --force to overwrite).
fluxlit new <name> Scaffold a minimal app.py in a new directory.
python -m fluxlit Equivalent entry to the fluxlit console script.

Options for dev / run include --host, --port, --log-level, --proxy-headers, --forwarded-allow-ips. fluxlit dev --reload reloads the API gateway process only via Uvicorn; the Streamlit subprocess is not restarted. Use --reload-scope=gateway (default) or restart fluxlit to pick up Streamlit UI changes.


Configuration

Precedence: CLI flags override environment variables; environment overrides project file defaults; then FluxlitSettings field defaults.

Project file

  • fluxlit.toml in the current working directory (top-level keys), or
  • [tool.fluxlit] in pyproject.toml if fluxlit.toml is absent.

If both exist, fluxlit.toml wins. Supported keys include target, gateway_host, gateway_port, log_level, api_mount_path, and root_path.

Example fluxlit.toml:

target = "app:app"
gateway_host = "127.0.0.1"
gateway_port = 8000
log_level = "info"

Environment (FluxlitSettings)

See Configuration and the API reference (fluxlit.config). Variables use the FLUXLIT_ prefix and optional .env file.

Variable Role
FLUXLIT_TITLE App title (default for FastAPI / UX).
FLUXLIT_GATEWAY_HOST / FLUXLIT_GATEWAY_PORT Defaults for binding (also used in settings; CLI overrides bind for dev/run).
FLUXLIT_ROOT_PATH ASGI root path behind a reverse proxy (passed through to FastAPI).
FLUXLIT_INTERNAL_API_BASE Set by the runtime for Streamlit-side ApiClient (includes /api).
FLUXLIT_ENABLE_REQUEST_LOGGING If true, log each API request (method, path, status) at INFO with request id context.

Suggested project layout

my_app/
├── app.py              # FluxLit instance, @app.api routes, @app.page handlers
├── pkg/                # Optional: Python package for discover_pages
│   ├── __init__.py
│   └── pages/          # call discover_pages("pages", package="pkg")
│       ├── __init__.py
│       └── reports.py  # def register(app): @app.page(...) ...
├── services/
├── static/
├── fluxlit.toml        # Optional defaults for CLI
└── .env                # FLUXLIT_* and secrets (do not commit)

Optional page packages: each pkg/pages/*.py module may define register(app: FluxLit) -> None that attaches @app.page handlers; call app.discover_pages("pages", package="pkg") after constructing FluxLit.


Package layout (src/fluxlit)

Autogenerated detail: Python API reference. Summary:

Module Purpose
app FluxLit application object
cli Typer CLI
client ApiClient (httpx) for server-side API calls
config FluxlitSettings
gateway ASGI router + HTTP/WebSocket proxy (request id context + debug logs)
project_config fluxlit.toml / [tool.fluxlit] loading
logging_context Request id ContextVar for gateway / API
runtime Subprocess orchestration, Uvicorn entry
streamlit_main Streamlit entry script (FLUXLIT_APP)
testing FluxLitTestClient (FluxLit-native API + Streamlit test helpers)
api Optional APIRouter helpers
auth Placeholder / future shared auth hooks

Testing

FluxLit uses the same “built-in” testing platforms you likely already know:

  • FastAPI: starlette.testclient.TestClient
  • Streamlit: streamlit.testing.v1.AppTest (version-dependent)

FluxLit also ships a small wrapper: FluxLitTestClient.

from fluxlit import FluxLit, FluxLitTestClient

app = FluxLit(title="Test")
client = FluxLitTestClient(app)

assert client.api_get("/healthz").status_code == 200

For Streamlit, you can run FluxLit’s Streamlit entrypoint via AppTest:

at = client.streamlit(target="my_app:app", extra_sys_path=".")

Development (contributors)

See Contributing on Read the Docs for setup, docs builds, and PR expectations.

pip install -e ".[dev]"
ruff check src tests && ruff format src tests
python -m pytest
python -m mypy src/fluxlit

Features: today vs planned

Available in current alphas

  • Single public port; managed Streamlit subprocess
  • Gateway: /api → FastAPI; HTTP + WebSocket proxy to Streamlit
  • @app.page + st.navigation integration; optional discover_pages for package layouts
  • fluxlit new, dev, run, doctor, build
  • fluxlit.toml / [tool.fluxlit] project defaults; ApiClient.get_model / post_model
  • Request id propagation (X-Request-ID) and optional API access logging
  • Typed package; Ruff + Mypy + Pytest in-tree; CI on GitHub Actions

Planned (see Roadmap on Read the Docs)

  • Hardened reload (Streamlit lifecycle), first-class health/metrics
  • Auth (JWT, sessions, proxy headers, OAuth)
  • Official Docker/Kubernetes examples beyond fluxlit build templates
  • OpenAPI-generated client (optional)

Philosophy

FluxLit should stay Pythonic (explicit, typed, easy to reason about), production-minded (proxy-safe, observable, deployable), and honest about Streamlit’s process/WebSocket model until a native ASGI path is proven.


License

MIT — see pyproject.toml metadata.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fluxlit-0.2.0.tar.gz (37.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fluxlit-0.2.0-py3-none-any.whl (30.1 kB view details)

Uploaded Python 3

File details

Details for the file fluxlit-0.2.0.tar.gz.

File metadata

  • Download URL: fluxlit-0.2.0.tar.gz
  • Upload date:
  • Size: 37.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fluxlit-0.2.0.tar.gz
Algorithm Hash digest
SHA256 8e3601ccfc199891a52a190c47cf7cadb4f84f25e959661ee56e8ae4d69e30e8
MD5 3bfcdb3261498c4a0cd4c6a5f6233269
BLAKE2b-256 3815c50d29f1947f6762af5dce203bf20796aadecdf815f3836f9be7e43724bd

See more details on using hashes here.

File details

Details for the file fluxlit-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: fluxlit-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 30.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fluxlit-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 73a31d391b735c100e8e6c4289b701935a469d5779e509a27a19bb33f9fec05b
MD5 607814940ba6fe73e65c3e128960e610
BLAKE2b-256 d7dfe571c8c0b3a61973c4d3a6fa4e2bd1bc08d287434394b04cd16f6d563f06

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page