This release is a pre-release and may not be stable for production use.
ViewForge
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.
✨ Features
- ✅ 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
📁 Project Structure
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
🚀 Getting Started
1. Define a handler
from viewforge.core.registry import handler
@handler()
def handle_click():
print("Button clicked!")
2. Use the handler in a Button
from viewforge.ui.elements import Button
Button("Click Me", on_click=handle_click)
3. Launch the app
from viewforge.core import App
App().run(lambda: [Button("Hi")])
🧠 How Events Work
-
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)
🌐 Routing Example
from viewforge.routing import route
@route("/user/<id>", "User Profile")
def user_profile(params, route):
return Text(f"Viewing user {params['id']}")
💡 Signals
from viewforge.state import Signal
count = Signal(0)
Button("Increment", on_click=lambda: count.set(count.get() + 1))
Text(lambda: f"Count: {count.get()}")
🔧 Advanced Tips
- 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
📦 Coming Soon
- ✅ FormGroup with validation
- 🧭 View decorators for route views
- 🌈 Light/dark theme switching
🧼 Philosophy
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.
Metadata
Release files for viewforge 0.1.0.dev2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| viewforge-0.1.0.dev2.tar.gz | 30.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| viewforge-0.1.0.dev2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 66.6 kB
Release files / viewforge-0.1.0.dev2.tar.gz
| Download URL | viewforge-0.1.0.dev2.tar.gz |
|---|---|
| Size | 30.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f0aa2078d892ef0cd1f437d34f6b9f1b94b148e09593d0b4d1cfc4389efa6ee0
|
|
BLAKE2b-256 checksum How to use checksums |
66af77dccee88228b1ddc9000e074f643c0327bc0582e0ac3363881f32bfbb59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.3
|
Release files / viewforge-0.1.0.dev2-py3-none-any.whl
| Download URL | viewforge-0.1.0.dev2-py3-none-any.whl |
|---|---|
| Size | 36.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
58c385cde19309e67f5440b157f12f498cdc950e3c6dcd1b73ba1d7b14337524
|
|
BLAKE2b-256 checksum How to use checksums |
2af03bef4cc11fedf551cad59dc53c6c7350404ad8bd8e985114941f3071d573
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.3
|