-
Notifications
You must be signed in to change notification settings - Fork 0
Store
HTeaLeaf introduces a reactive state layer inspired by modern frontend frameworks.
It allows you to define global or user-specific state directly in Python, and bind it to HTML components that update automatically when the state changes.
HTeaLeaf includes a full server-driven reactivity system built around three components:
-
Store: Global shared state -
AuthStore: Per-user state bound to sessions -
SuperStore: The orchestrator that connects and synchronizes stores through HTTP and JavaScript
A Store is a shared, reactive state container that lives on the server side and synchronizes with the client through HTeaLeaf’s reactivity engine.
from HTeaLeaf.State.Store import Store
cstore = Store({"counter": 1})Each Store behaves like a reactive dictionary you can read and modify values, and any UI elements bound via .react() automatically update when the data changes.
HTeaLeaf stores can be accessed using path-like keys, similar to JSON pointers. This allows deep updates inside nested data structures such as lists or dictionaries.
For example:
store = Store({"todo": [{"value": "Buy milk", "done": False}]})This is used by the JavaScript JSCode helper:
store.js.update("todo/0/done", True)@app.route("/counter")
def counter():
return div(
rButton("-").attr(onclick=cstore.do.update("counter", -1)),
h3(cstore.react("counter")),
rButton("+").attr(onclick=cstore.do.update("counter", 1)),
)AuthStore behaves just like Store, but each user session has its own isolated copy.
from HTeaLeaf.Magic.Store import AuthStore
from HTeaLeaf.Server.Server import Session
def auth_session(session: Session):
if session.has("userName"):
return session["userName"]
return None
todoStore = AuthStore(auth_session, {"todo": []})Each authenticated user gets their own instance of the todo data, independent from others.
@app.route("/")
def home(session):
if not session.has("userName"):
return redirect("/login")
return div(
[elementoCompra(idx, t) for idx, t in enumerate(todoStore.auth(session).read("todo"))],
button("Add Task").attr(onclick=JSCode(todoStore.do.set("todo", {"done": false, "value": val}))
)Each logged-in user interacts with their own store content, persisted in memory and linked to their session ID.
SuperStore acts as the reactivity controller for all stores. It connects them to the app and automatically registers endpoints for synchronization and data mutation.
from HTeaLeaf.State.Store import SuperStore
from HTeaLeaf.Server.WSGI import WSGI
app = WSGI()
SuperStore(app)Once initialized:
- All Store and AuthStore instances become discoverable.
- The framework exposes internal HTTP endpoints for reading and writing store data.
- The Store.js objects (injected into the frontend) communicate with these endpoints.
You typically only need one SuperStore per application.
When the client triggers an update, like:
store.do.update("todo/0/done", True)translated in the frontend to:
store_xyz.update("todo/0/done", true)the call is routed to an automatically exposed backend endpoint, typically something like
POST /api/_store/{api_id}/todo/0/doneSuperStore:
- Parses the path (todo/0/done).
- Locates the right Store or AuthStore instance.
- Applies the mutation.
This allows fully reactive data flow over plain HTTP, no WebSockets required.
from HTeaLeaf.Magic.Store import SuperStore, Store, AuthStore
from HTeaLeaf.Server.Server import Session
from HTeaLeaf.Server.WSGI import WSGI
app = WSGI()
SuperStore(app) # register the orchestrator
globalStore = Store({"counter": 0})
def auth_session(session: Session):
return session["userName"] if session.has("userName") else None
todoStore = AuthStore(auth_session, {"todo": []})After this, globalStore and todoStore are automatically exposed and reactive.
+-------------+ +----------------+ +---------------+
| Python App | <---> | SuperStore | <---> | Client (JS) |
+-------------+ +----------------+ +---------------+
▲ ▲ ▲
| | |
| Store updates | HTTP fetch/update |
|-----------------------|------------------------|
- SuperStore handles orchestration, routing, and propagation.
- Store / AuthStore define the reactive data models.
- JSDO translates Python actions into client-side JS that calls the correct store endpoints.