Skip to content
oldmangan edited this page Oct 11, 2026 · 20 revisions

wapyt (wA PyTincture widgetset) is a DHTMLX-free widgetset for pyTincture. You declare widgets in Python; they render as plain DOM through wapyt's bundled JavaScript, inside Pyodide in the browser. It is the MIT-licensed alternative to dhxpyt, which wraps the commercial DHTMLX suite.

Apps built on it: Monguana (MongoDB manager), IguanaXterm (SSH/SFTP/remote-desktop client), wAwesomeChat (multi-provider AI chat) and the the Orpheus media server's browser player.

Start here

I want to… Read
Build my first wapyt app Getting Started
See every widget at a glance Widget Catalog
Lay out a page and mount widgets Layout and MainWindow
Handle events and call the backend Events and Async
Show a toast or ask for confirmation Message
Build a form: fields, buttons, sections, validation Form
Show nested items people can tick or drag around Tree
Open a window people can move, resize and stack Window
Draw a chart, or fill a resizable dashboard with them Chart
Show a calendar people can book and drag appointments in Scheduler
Play video or music, with a queue, a docked music bar and subtitles MediaPlayer
Connect the player to my own media server, or play files from disk MediaPlayer: connecting your media server
Put buttons and dropdown menus along the top Toolbar
Add a right-click menu ContextMenu
Add a File / Edit / View menu bar MenuBar
Show draggable cards, or lists you can move items between Listbox
Run a board of columns (to do / doing / done) Kanban
Show progress ProgressBar
Page through results Pagination
Let people resize panes Layout and MainWindow
Open a popover or add tooltips Popup and tooltips
Change colours, fonts, icons Theming and Icons
Put user or model data on screen safely Security and Escaping
Move from dhxpyt, or find what wapyt lacks Comparison with dhxpyt
See what is planned Roadmap
Fix a problem Troubleshooting
Work on wapyt itself Development

A minimal app

# dashboard.py -- the browser entrypoint
import widget  # noqa: F401  (literal __widgetset__ = "wapyt", __version__ = "0.2.0")
from wapyt import CellConfig, ColumnConfig, DataTableConfig, LayoutConfig, MainWindow

APP_ENTRYPOINT = "Dashboard"


class Dashboard(MainWindow):
    layout_config = LayoutConfig(rows=[
        CellConfig(id="header", height="auto", html="<h3>Dashboard</h3>"),
        CellConfig(id="main", grow=1),
    ])

    def load_ui(self):
        self.set_theme("dark")
        table = self.add_datatable("main", DataTableConfig(
            columns=[ColumnConfig(id="name", header="Name")],
            rows=[{"id": "1", "name": "Hello, wapyt"}],
        ))

Getting Started covers the rest: widget.py, the browser wheel and service.py.

How it works

Every widget follows one path: a *Config dataclass → .to_dict() (camelCase) → js.wapyt.<Widget>.new(root, payload). Events come back through .on_* handlers. The Python side is a typed facade and holds no widget state; the JS in wapyt/assets/ does the rendering. pyTincture hash-verifies those assets before loading them.

Clone this wiki locally