The full-stack Python application framework

Build web apps in Python.Right down to the browser.

Pytincture packages browser-safe Python for Pyodide, keeps privileged work on FastAPI, and generates an explicit bridge between the two. One language. Two deliberate runtimes.

PythonPyodideFastAPIASGI
Atlas Library · Pytincture app application anatomy
app.pybrowser
1import json
2from dhxpyt.grid import GridConfig
3from py_ui_data import py_ui_data
4
5data = json.loads(py_ui_data().dataset())
6grid_config = GridConfig(
7    columns=columns, data=data
8)
9self.book_grid = self.tabbar.add_grid(
10    id="tab1", grid_config=grid_config
11)
browser py_ui_data().dataset() generated BFF policy + transport server FastAPI
Browser PythonPyodide-backed runtime
Generated BFFExplicit server boundary
FastAPI serviceTrusted application code
Static modeNo backend required

More than a browser runtime

The application framework around your Python.

Pytincture handles the path from Python modules to a running browser application: packaging, startup, server calls, identity, assets, and production signals.

Browser runtime01

Python lives in the interface.

Package application modules and declared dependencies for a deterministic Pyodide runtime.

Application delivery02

One service, every application asset.

Serve routes, browser packages, public files, and trusted APIs from a configurable FastAPI/ASGI application.

Backend for frontend03

A Python-shaped bridge—not a mystery tunnel.

Decorated server classes become class-shaped browser proxies with explicit methods, policies, and streaming support.

Identity & policy04

Authentication belongs at the boundary.

Local login, Google OAuth, explicit-tenant Microsoft OAuth, and SAML—with authorization enforced on the server.

Production operations05

Signals you can operate.

Health, readiness, structured logs, correlation IDs, bounded work, and replica-safe signed sessions.

Reproducible assets06

The browser package is deliberate.

Exact pins or SHA-locked wheels, hashed manifests, filesystem containment, and a Pyodide software bill of materials.

One language, two runtimes

Put each kind of Python where it belongs.

Browser code owns interaction. Server code owns credentials, policy, and trusted systems. Pytincture makes the handoff visible and removes the repetitive transport glue.

01
Browser

Package the application

UI modules and declared dependencies become browser-ready assets for a named Pyodide lifecycle.

load → install → import → run
02
Boundary

Generate the bridge

Class-shaped proxies carry calls over explicit HTTP methods, with CSRF and replay protection where required. Policy stays server-owned.

@backend_for_frontend
03
Server

Execute trusted work

Authentication and policy run before protected application code is imported, constructed, or called.

user → policy → systems
browser / reports.py
from reports import Reports

status = Reports().status()
self.badge.set_value(status["state"])
server / reports.py
@backend_for_frontend
class Reports:
    def status(self):
        return {"state": "ready"}

Optional Python UI toolkit

Python-first does not mean primitive UI.

dhxpyt wraps DHTMLX components for Python-first layout, configuration, and events inside Pytincture applications.

Component labdhxpyt 0.9.16
Application modulesExample workspace
ModuleRuntimeBoundaryStatus
workspace.pyBrowserRunning
reports.pyServerBFFReady
widget.pyPackageResolved
auth.pyServerPolicyProtected
Application lifecycleStage timings · example
browser service
load runtimebrowser
install packagesbrowser
import appbrowser
authorize BFFserver
render UIbrowser
New application

Configure a workspace

Form, combobox, datepicker, and message components composed from Python.

Deployment review streaming

Check whether the application is ready to receive traffic.

PyReadiness is green.
/readyz reports the modules path, frontend runtime, and configured stores are available.

Ask the application…
Explore dataGrid · Chart · Tree · Listbox · Pagination
Collect inputForm · Combobox · Calendar · Timepicker · Colorpicker
Structure appsLayout · Sidebar · Tabbar · Toolbar · Menu · Window · Ribbon · Popup
Build workflowsKanban · Cardflow · Cardpanel · Chat · Message · Slider
24 modulesExplore the complete widgetset ↗

Licensing: Pytincture core is MIT licensed. dhxpyt is GPL-2.0; bundled DHTMLX assets may require GPL, evaluation, or commercial licensing.

One framework, two delivery modes

Choose the infrastructure your application needs.

Start from the same browser-Python foundation, then keep the application static or add the trusted service boundary.

application.pyPython
Static

A browser application with no backend.

Run inline Python from static hosting with Pyodide and pinned browser dependencies.

HTMLPyodideUI
  • static hosting
  • manual or automatic startup
  • no host Python process
Service

A complete ASGI application.

Add trusted code, authenticated data, generated BFF calls, managed assets, and optional MCP exposure.

BrowserFastAPISystems
  • authentication and policy
  • BFF methods and streams
  • health, readiness, and logs

Built for operational use

The operational shape is part of the framework.

Add only what the deployment needs. The core exposes defined contracts instead of leaving production behavior to convention.

Read the production guide ↗
PyPytincture appAuthBFF policyStreamingLifecycleHealthLogsAsset locksMCP maps

Start with a real application

From three Python files to a running browser UI.

Configure the service, define a browser entry point, and declare the UI package Pytincture should resolve.

Preview the 1.0 API
python -m pip install pytincture==1.0.0rc2
Requires CPython 3.13 or 3.14. Current stable remains 0.10.7; pin the preview exactly while evaluating 1.0.
  1. 01Create the service configuration
  2. 02Write the browser entry point
  3. 03Declare the widgetset version
  4. 04python -m uvicorn service:app --port 8070
Open the maintained quickstart
1from pathlib import Path2from pytincture import PytinctureConfig, create_app34HERE = Path(__file__).resolve().parent56app = create_app(7    PytinctureConfig(8        modules_path=str(HERE),9        default_application="hello",10    )11)
1import js2import widget3from dhxpyt.layout import MainWindow45class hello(MainWindow):6    def load_ui(self):7        js.document.getElementById("maindiv").innerHTML = (8            "<h1>Hello from Pytincture</h1>"9            "<p>Python is running in your browser.</p>"10        )
1__widgetset__ = "dhxpyt"2__version__ = "0.9.16"
localhost:8070/hello
Browser outputHello from Pytincture

Python is running in your browser.

1.0 readinessRC2 has passed qualification.

The public contracts, qualification matrix, and production gates are in place. Final 1.0 remains in its required observation period and awaits release approval.

RC2 notes ↗Migration guide ↗

Start in Python

Build the browser in Python. Keep trust on the server.

Start with the framework, then bring in BFF access, authentication, and dhxpyt as the application grows.

Start building View the source
Copied to clipboard