Contents Menu Expand Light mode Dark mode Auto light/dark, in light mode Auto light/dark, in dark mode Skip to content
FluxLit 0.13.3
FluxLit 0.13.3

User guide

  • Quick start
  • Architecture
  • Configuration
  • Command-line interface
  • Deployment
  • Platform recipes
  • Production TLS and edge headers
  • Secrets lifecycle
  • Observability
  • Rate limiting
  • Security architecture
  • URL session continuity (no cookies)
  • URL sessions, query tokens, and email links (security)
  • Deep links and query parameters
  • Cookbook
  • Streamlit → FastAPI: ApiClient patterns
  • Streamlit pages: typing, Depends, and manifests
  • Migrating to JWT and OIDC
  • Auth recipes
  • Troubleshooting
  • Runbooks
  • Testing
  • Contributing
  • Contributing to FluxLit

Reference

  • Python API reference
  • Changelog
  • Changelog
  • Support matrix
  • Roadmap
  • FluxLit — Development Roadmap
  • Index
Back to top
View this page
Edit this page

Deep links and query parameters¶

FluxLit serves the Streamlit shell on the public app base (respecting FLUXLIT_ROOT_PATH / FLUXLIT_STREAMLIT_PUBLIC_PATH) and the API under FLUXLIT_API_MOUNT_PATH (default /api). Email links, invite flows, and password-reset entrypoints should point at the Streamlit URL with query parameters, not at POST-only API routes. For security when those parameters carry session or reset tokens, read URL sessions, query tokens, and email links (security).

Build links from FastAPI¶

Use urls with the current starlette.requests.Request so links match subpaths and FLUXLIT_PUBLIC_BASE_URL:

from fastapi import FastAPI, Request

app = FastAPI()
# ... attach your FluxLit instance as ``fl`` ...

@app.get("/internal/invite-link")
def invite_link(request: Request, token: str) -> dict[str, str]:
    return {
        "ui": fl.urls.page_url(
            request,
            "/",
            query={"page": "Accept invite", "token": token},
        ),
    }

page_url() is an alias for for_page(); both append the configured public mount and percent-encode query values.

Read query parameters in Streamlit¶

fluxlit.query_params() normalizes st.query_params to a dict[str, str], using the first value when Streamlit exposes a list (multiple values for one key):

from typing import Any

import streamlit as st
from fluxlit import query_params

def show_token(st: Any) -> None:
    params = query_params(st)
    token = params.get("token", "")

For Pydantic-validated query models (single keys, defaults, coercion), use parse_query_params() — see Streamlit pages: typing, Depends, and manifests.

Optional ?page= routing¶

When you send users to the app root with a page title or path segment in the query string, fluxlit.match_nav_page() resolves against a sequence of pages ((path, title, handler) tuples, :class:~fluxlit.pages.records.PageRecord instances, or similar duck-typed rows). The unified Streamlit entrypoint (:mod:fluxlit.streamlit.main) passes the same ordered :attr:~fluxlit.app.FluxLit.page_records list it uses to build st.navigation (including :meth:~fluxlit.app.FluxLit.navigation sort when NavigationModel.order is set), not the raw :attr:~fluxlit.app.FluxLit.pages tuple view, so ?page= tie-breaking follows the sidebar order you see in the UI.

You can still call fluxlit.match_nav_page() yourself when you need custom logic beyond navigation:

from typing import Any

from fluxlit import match_nav_page, query_params
from fluxlit.app import FluxLit
from fluxlit.client import ApiClient


def apply_deep_link(st: Any, client: ApiClient, fl: FluxLit) -> None:
    _ = client
    params = query_params(st)
    hit = match_nav_page(params, list(fl.page_records), page_key="page")
    if hit:
        path, title = hit
        # drive your own UI (e.g. default widget values) from path/title

If you call fluxlit.match_nav_page() yourself, pass the same ordered list[PageRecord] the entrypoint would use (after optional :meth:~fluxlit.app.FluxLit.navigation sorting via :func:~fluxlit.streamlit.nav_order.navigation_sort_key), not fl.pages, so ordering matches the sidebar and ?page= resolution.

Matching order: exact title, exact path, Streamlit-style slug ("/" → "home"), then path segments with slashes stripped from both sides (so reports/ can match /reports).

The entrypoint also applies PageMeta.children for sidebar ordering (see :mod:fluxlit.streamlit.nav_build). If those edges contain a cycle, FluxLit emits a UserWarning and falls back to appending unresolved pages in registration order.

Security: tokens and PII in URLs¶

Anything in the query string can leak via:

  • Referer headers when users follow outbound links to other sites.

  • Browser history, shared screenshots, and shoulder-surfing.

  • Access logs and crash reports unless values are redacted (FluxLit’s gateway can redact configured session query keys; see Observability and URL session continuity (no cookies)).

Prefer short-lived, single-use tokens, HTTPS everywhere, and clearing sensitive query keys after read (where Streamlit allows) once you have copied values into st.session_state. For durable state across reloads without putting secrets in the URL, consider URL session continuity (no cookies) patterns instead.

Testing with FluxLitTestClient and AppTest¶

API routes that return page_url should be exercised through FluxLitTestClient so the same gateway prefix rules apply as in production. You can also pass query_params= to :meth:~fluxlit.testing.FluxLitTestClient.streamlit instead of mutating AppTest manually.

For Streamlit AppTest, set query values on the runner before run():

from streamlit.testing.v1 import AppTest
from fluxlit import query_params
import textwrap

script = textwrap.dedent(
    '''
    import streamlit as st
    from fluxlit import query_params

    p = query_params(st)
    st.text_input("Token", value=p.get("token", ""), key="tok")
    '''
)
at = AppTest.from_string(script, default_timeout=10)
at.query_params["token"] = "from-email"
at.run()
assert at.text_input(key="tok").value == "from-email"

See also Testing for FLUXLIT_TESTS, multipage smoke tests, and streamlit_main_path().

Next
Cookbook
Previous
URL sessions, query tokens, and email links (security)
Copyright © FluxLit contributors
Made with Sphinx and @pradyunsg's Furo
On this page
  • Deep links and query parameters
    • Build links from FastAPI
    • Read query parameters in Streamlit
    • Optional ?page= routing
    • Security: tokens and PII in URLs
    • Testing with FluxLitTestClient and AppTest