diff --git a/README.md b/README.md index e04e8da..0cc15af 100644 --- a/README.md +++ b/README.md @@ -17,41 +17,51 @@ and HTeaLeaf takes care of keeping everything in sync automatically. --- +## 📦 Installation + +```bash +pip install htealeaf +``` + +Requires **Python ≥ 3.10**. Bring your own WSGI/ASGI server (`wsgiref` from the +standard library works for local development, `uvicorn` for ASGI). + +--- + ## 🚀 Quick Example ```python -from HTeaLeaf import Store, SuperStore, HTeaPot, adapters -from HTeaLeaf.Elements import div, h3, button +from htealeaf import HteaLeaf, SuperStore, Store, adapters +from htealeaf.elements import div, h3, button -app = HTeaPot(adapters.WSGI) -SuperStore(app) +app = HteaLeaf(adapters.WSGI) +SuperStore(app) # wires the store API routes and client-side runtime counter = Store({"count": 0}) @app.route("/") def home(): return div( - button("-").attr(onclick=counter.js.update("count", -1)), - h3(counter.react("count")), - button("+").attr(onclick=counter.js.update("count", 1)), + button("-").attr(onclick=counter.js.update("count", counter.read("count") - 1)), + h3(counter.read("count")), + button("+").attr(onclick=counter.js.update("count", counter.read("count") + 1)), ) -application = app.wsgi_app - if __name__ == "__main__": from wsgiref.simple_server import make_server - with make_server("", 8000, application) as server: + with make_server("", 8000, app) as server: print("Serving at http://127.0.0.1:8000") server.serve_forever() ``` -Visit `http://127.0.0.1:8000` a fully reactive counter, zero JavaScript written by hand. +Visit `http://127.0.0.1:8000` — a fully reactive counter, zero JavaScript written by hand. You can also write client-side logic directly in Python using the `@js` decorator, and HTeaLeaf will compile it to JavaScript automatically: ```python -from HTeaLeaf.JS import js +from htealeaf.js import js +from htealeaf.js.common import console @js def greet(event): @@ -60,22 +70,50 @@ def greet(event): button("Click me").attr(onclick=greet) ``` +> **Note:** the `HteaLeaf` app object is itself the WSGI/ASGI callable — pass it +> straight to your server (`make_server("", 8000, app)`), there is no separate +> `.wsgi_app` attribute. + +--- + +## ⚡ ASGI + +The same app runs under ASGI by swapping the adapter: + +```python +from htealeaf import HteaLeaf, SuperStore, adapters + +app = HteaLeaf(adapters.ASGI) +SuperStore(app) +# ... routes ... +``` + +```bash +uvicorn myapp:app +``` + +A `CGI` adapter is also available (`adapters.CGI`). + --- ## ✨ Key Features - **Declarative HTML**: build DOM trees with a fluent Python DSL, no templates needed - **Reactive server state**: `Store` objects stay in sync with the UI automatically -- **Local route state**: `use_state()` for state scoped to a single route +- **Local route state**: `use_state()` for state scoped to a single route (client-side, no server round-trip) - **Python → JS transpilation**: write client-side logic in Python with `@js`; HTeaLeaf compiles it - **Session support**: per-user state with `AuthStore` and cookies +- **Multiple transports**: WSGI, ASGI, and CGI adapters behind one API --- -## 📦 Installation +## 🧩 Running the demo + +The repository ships a small demo app: ```bash -pip install htealeaf +python -m demo.demo_wsgi # WSGI on http://127.0.0.1:8000 +uvicorn demo.demo_asgi:app # ASGI ``` --- @@ -89,9 +127,10 @@ pip install htealeaf - [x] Local route state (`use_state()`) - [x] Session support - [x] Client-side-only state (no server round-trip) +- [x] Async first architecture - [ ] Render optimisation - [ ] Persistent Store backends (Redis, SQL, …) -- [ ] Async first architecture +- [ ] Session expiration (TTL + eviction) — in progress on `feature/alb-28` - [ ] CLI - [ ] Build system to static assets @@ -99,7 +138,8 @@ pip install htealeaf ## 📖 Documentation -Full documentation is available in the [Wiki](https://github.com/Az107/HTeaLeaf/wiki/Welcome-to-the-HTeaLeaf!). +- Full documentation: [Wiki](https://github.com/Az107/HTeaLeaf/wiki/Welcome-to-the-HTeaLeaf!) +- [`docs/PY2JS.md`](docs/PY2JS.md) — design notes for the Python → JavaScript (`JSCode`) interop layer ---