Skip to main content

millwork

A modern UI framework for Python

CI Python 3.12 or newer Apache-2.0

A millwork page: three stat tiles with trends, a bar chart and a sortable table, in the default theme.

A page is a Python function of the session's state. A handler changes the state, the page renders again, and the browser receives a patch. The React bundle ships inside the package, so a project is Python only.

import millwork as mw
from millwork import ui
from pydantic import BaseModel


class State(BaseModel):
    clicks: int = 0


app = mw.App("hello", state=State)


@app.page("/")
def home(s: mw.Session[State]) -> ui.Component:
    return ui.Page(
        ui.Text(f"Clicked {s.state.clicks} times."),
        ui.Button("Add one", on_click=lambda s, _: setattr(s.state, "clicks", s.state.clicks + 1)),
    )
uv add git+https://github.com/DvGils/millwork
uv run millwork run app.py

What is in the box

  • A catalogue of components on shadcn/ui: layout, text, inputs, feedback, tables, charts, forms from Pydantic models, files, tasks with progress, and a chat surface that streams replies from Python.
  • One model of state. Python owns the state; a control is owned by Python or by the browser, and the page says which.
  • Long work as tasks, with progress, steps and cancellation drawn by the page, and chat replies that stream text, reasoning and tool steps.
  • Files over the session's socket. Uploads, downloads and inline images travel on the same connection as everything else, so replicas need no sticky routing and no shared storage.
  • Sign-in with password, OAuth and proxy-header providers behind one on_login hook, and a theme file in the shadcn token vocabulary for colors, fonts and logos.
  • A test harness that drives a page without a browser: open it, click, change, submit, and read what the tab would have received.
  • One process to run. millwork run serves an app on a port or a unix socket, behind a proxy and under a path prefix, with a health route for the host.

The manual

The manual is a millwork app. Every example in it runs, with the Python code beside it:

uv run millwork docs

Then open http://127.0.0.1:8008. The chapters cover pages and routing, state and handlers, signing in, theming, testing and running, and every component has a live example.

Status

millwork is still in beta.

Developing millwork

Python is managed with uv, the bundle with pnpm; only bundle/ needs Node.

uv run pytest -q                       # the Python suite
uv run mypy src && uv run ruff check src tests
pnpm -C bundle exec tsc --noEmit       # the bundle's types
CI=1 pnpm -C bundle exec vitest run    # the bundle's unit tests
CI=1 pnpm -C bundle build              # rebuilds src/millwork/_bundle/dist

A change to the bundle is committed together with the rebuilt dist, so every checkout runs without Node. The manual's pages under src/millwork/manual/pages are the gallery a bundle upgrade is judged against.

Releasing

A release is a tag. Write the version's section in CHANGELOG.md, set the version with uv version 0.2.0, commit, tag v0.2.0 and push the tag. The release workflow waits for approval, checks the tagged commit, builds the wheel, publishes it to PyPI and makes the GitHub release from the changelog section.

License

Apache-2.0.

Metadata

Release files for millwork 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for millwork 0.1.0
File Interpreter ABI Platform Actions
millwork-0.1.0-py3-none-any.whl Python 3 none any Details for millwork-0.1.0-py3-none-any.whl

Release files / millwork-0.1.0-py3-none-any.whl

Download URL millwork-0.1.0-py3-none-any.whl
Size 1.2 MB
Tags Python 3
SHA-256 checksum
How to use checksums
b7f9b7969ad73d47d95f728b7f91831962c150a953269716eb4322a0453c3184
BLAKE2b-256 checksum
How to use checksums
2aba4dc51f375d2456eb1b12d478e3d8eae66b5ce3c8ba277564240d87daa67d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Security for millwork 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 1 file in this release has been uploaded with provenance metadata.

Attestation for millwork-0.1.0-py3-none-any.whl

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page