⚠️ Note: This project is currently under active development. APIs and features are subject to change.
ViewForge is a modern Python desktop UI framework that renders HTML and web components inside a pywebview window.
It supports component-based rendering, declarative event registration, reactive state with signals, and flexible routing — all in Python.
- ✅ Component-based architecture (Text, Button, Stack, etc.)
- 🔗 Declarative event binding via
@handler() - 🧠 Central Python event router for dynamic dispatch
- 🧩 Flexible styling via CSS-style dicts
- 🌐 Built-in router with support for path params and query strings
- ⚡ Hot reload with
Ctrl+R - 🔁 Signals for reactive state
- 📦 Modular, extensible, no build step required
viewforge/
├── core/ # App, Component, Registry
├── ui/ # elements/, layout/, links/
├── routing/ # route decorators, RouterView
├── state/ # Signal, Store
├── rendering/ # DOM and HTML rendering logic
├── utils/ # CSS, JS utilities, case handling
├── adapters/ # Optional UI system adapters (Shoelace, BeerCSS)
├── plugins/ # Debug tools, hot reload
└── main.py # App entry point
from viewforge.core.registry import handler
@handler()
def handle_click():
print("Button clicked!")from viewforge.ui.elements import Button
Button("Click Me", on_click=handle_click)from viewforge.core import App
App().run(lambda: [Button("Hi")])-
You define Python handlers with
@handler()→ they get a unique name likeon_handle_click -
Components like
Buttonrender HTML like:<sl-button onclick="vf('on_handle_click')">Click</sl-button>
-
The global
vf(...)JS function relays to Python viapywebview.api.handle_event(...) -
The Python router calls your function:
def handle_event(self, name, *args): return handler_registry.get()[name](*args)
from viewforge.routing import route
@route("/user/<id>", "User Profile")
def user_profile(params, route):
return Text(f"Viewing user {params['id']}")from viewforge.state import Signal
count = Signal(0)
Button("Increment", on_click=lambda: count.set(count.get() + 1))
Text(lambda: f"Count: {count.get()}")- All components support
style={}for CSS properties - You can nest layout containers like
Stack,Box, or build your own - Router supports dynamic segments and query strings
- ✅ FormGroup with validation
- 🧭 View decorators for route views
- 🌈 Light/dark theme switching
ViewForge is minimal by design — no JavaScript build steps, no virtual DOM diffing — just clean Python and direct HTML rendering.
Build UIs in Python. Render like the web.