Rust-backed framework for building websites in pure Python
Project description
ztml
A Rust-backed framework for building websites in pure Python. ZTML allows you to define HTML/CSS/JS using only Python expressions with as much autocompletion support as I could reasonably add. Inspired by FastHTML.
Install
pip install ztml
HTML
Every HTML element has a corresponding constructor function. Attributes are set via chained builder methods. Call render() to get an HTML string.
from ztml import *
page = render(
Html(
Head(Meta().charset("utf-8"), Title("My App")),
Body(
H1("Hello, ztml!"),
P("Build websites with Python.").cls("intro"),
A("GitHub").href("https://github.com").target("_blank"),
),
)
)
Attributes chain naturally:
Div(
Input().type("text").name("q").placeholder("Search...").autofocus(),
Button("Go").type("submit"),
).cls("search-box").id("search")
Use Fragment to group elements without a wrapper tag, and Raw to inject unescaped HTML:
Fragment(
H1("Title"),
P("Paragraph"),
Raw("<hr/>"),
)
Style
Build CSS with Rule, Media, Keyframes, and Frame. Wrap them in Style() to render a <style> block.
Style(
Rule("body").margin("0").font_family("system-ui, sans-serif"),
Rule(".container").display("flex").gap("1rem").padding("2rem"),
Rule(".container > .sidebar").width("250px").flex_shrink("0"),
Rule(".container > .main").flex("1"),
Media("(max-width: 768px)",
Rule(".container").flex_direction("column"),
Rule(".container > .sidebar").width("100%"),
),
Keyframes("fadeIn",
Frame("from").opacity("0").transform("translateY(-10px)"),
Frame("to").opacity("1").transform("translateY(0)"),
),
Rule(".card").animation("fadeIn 0.3s ease-out"),
)
CSS property methods are generated from W3C specs — every standard property is available with autocompletion. Use .prop("custom-property", "value") for anything not covered.
Inline styles work too:
Div("styled").style(InlineStyle().color("red").font_weight("bold"))
Script
Build JavaScript with On event handlers and RawJs. Wrap them in Script() to render a <script> block.
Script(
On.click("#increment", """
let count = document.getElementById('count');
count.textContent = parseInt(count.textContent) + 1;
"""),
On.document_ready("console.log('page loaded')"),
On.submit("#my-form", """
event.preventDefault();
alert('submitted!');
"""),
RawJs("function greet(name) { alert('Hello, ' + name); }"),
)
Available event helpers: On.click, On.submit, On.change, On.input, On.keydown, On.keyup, On.mouseover, On.mouseout, On.focus, On.blur, On.document_ready, and On.event for custom events.
Putting It Together
A complete page with HTML, CSS, and JS:
from ztml import *
def page():
return Html(
Head(
Meta().charset("utf-8"),
Title("Counter"),
Style(
Rule("body").font_family("system-ui").display("flex")
.justify_content("center").padding("4rem"),
Rule("button").padding("0.5rem 1rem").font_size("1.2rem")
.cursor("pointer").border_radius("4px"),
Rule("#count").font_size("3rem").margin("1rem 0"),
),
),
Body(
H1("Counter"),
P("0").id("count"),
Button("Increment").id("increment"),
Script(
On.click("#increment", """
let el = document.getElementById('count');
el.textContent = parseInt(el.textContent) + 1;
"""),
),
),
)
print(render(page()))
Server
ztml includes a built-in server for HTMX-powered apps, built on Starlette and Uvicorn.
from ztml import *
from ztml.server import rt, serve
@rt('/')
def get():
return Html(
Head(Title("Counter")),
Body(
H1("Counter"),
P("0").id("count"),
Button("Increment").hx_post("/increment").hx_target("#count"),
),
)
count = 0
@rt('/increment')
def post():
global count
count += 1
return P(str(count)).id("count")
serve() # localhost:5001
Key features:
- Method inference — the HTTP method is inferred from the function name (
get,post,put,delete, etc.) - Auto HTMX — full-page responses (
<html>) get the HTMX script auto-injected - Path parameters —
@rt('/greet/{name}')extractsnameas a function argument - Request access — add a
requestparameter to access the StarletteRequestobject - Element rendering — handlers return ztml elements, automatically rendered to HTML
Building from Source
Prerequisites: Rust toolchain, Python 3.12+, uv.
# Install dependencies and build the Rust extension
uv sync
# For iterative development (faster rebuilds)
uv run maturin develop
# Generate .pyi type stubs for autocompletion
cargo run --bin gen_stubs --no-default-features
To build a distributable wheel:
maturin build --release
# Output in target/wheels/
Examples
# Generate a static HTML page to stdout
uv run examples/static_page.py > page.html # (open page.html in your browser!)
# HTMX counter app (localhost:5001)
uv run examples/counter_server.py
# HTMX todo app (localhost:5001)
uv run examples/todo_server.py
Running Tests
uv run pytest
# Rust unit tests
cargo test -p ztml-core
How codegen works
build.rs reads HTML element definitions from webtags and CSS property specs from w3c/webref, stored in specs/. From these it generates:
- Element constructors — one Python function per HTML tag
- CSS property methods — on
Rule,InlineStyle, andFrame - Enum classes — for CSS keyword values and HTML attribute values
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ztml-0.1.0.tar.gz.
File metadata
- Download URL: ztml-0.1.0.tar.gz
- Upload date:
- Size: 54.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
956acc68906e5ad738d52c6fb66aa89d79390ff0060d105c70da2dbcb745cbe5
|
|
| MD5 |
43bdceea16179701af5d4132980bcda0
|
|
| BLAKE2b-256 |
778b6bba455a4ec769251e238c5edae4b9c7655675ef7e0b19def6449e16d0ab
|
File details
Details for the file ztml-0.1.0-cp314-cp314-win_amd64.whl.
File metadata
- Download URL: ztml-0.1.0-cp314-cp314-win_amd64.whl
- Upload date:
- Size: 1.1 MB
- Tags: CPython 3.14, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c880ca424a2313976d56986ed23a3e35d05927f1325d6de7eb1b8b41f6219b2
|
|
| MD5 |
3989ca714ef492eef4dea7ed61c22e2e
|
|
| BLAKE2b-256 |
a3f7530f062a814588fa0e991951f5cba6b941211e29d645a53848619acdbb72
|
File details
Details for the file ztml-0.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: ztml-0.1.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.14, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
548e1fb9eca042e38b3ba1e4d9b59cae525e1f442e2533438ef84fd90b59224c
|
|
| MD5 |
8a6aa043a7a54c76db3793838058cfed
|
|
| BLAKE2b-256 |
97355b49302e6388725144f40f922a24798fa95705d1587b10309d0ce515cc8c
|
File details
Details for the file ztml-0.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: ztml-0.1.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.6 MB
- Tags: CPython 3.14, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
264117a7c79ecc2a0a1fe84c43aecac642114f7c64685cf851b756b64521ccf7
|
|
| MD5 |
261d58f0049876dc2afb7568514556f3
|
|
| BLAKE2b-256 |
734e03cb7a797797d34e593e2e3107e9145f7d5ea68adbabb47d03631ed8907d
|
File details
Details for the file ztml-0.1.0-cp314-cp314-macosx_11_0_arm64.whl.
File metadata
- Download URL: ztml-0.1.0-cp314-cp314-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.14, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b242ce9ddaede2c82c53872bce2be7874e98099bf84ed5e30f12f07c7bfa4fe
|
|
| MD5 |
81b0da86782ace3d13c7ff4e2db4e3f8
|
|
| BLAKE2b-256 |
972e0c0fdce1951d0fe13a7e3a12def717f20f13d7e2b3dfd3b2756d26191cbe
|
File details
Details for the file ztml-0.1.0-cp314-cp314-macosx_10_12_x86_64.whl.
File metadata
- Download URL: ztml-0.1.0-cp314-cp314-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.3 MB
- Tags: CPython 3.14, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa6bd93e2438a8851f09a89d19b628f058640df7d6765d7d0c2616b71641d591
|
|
| MD5 |
9e20f56c2267a651100eb42a0d829d84
|
|
| BLAKE2b-256 |
58a23b21e78dd84a78a6dee9742670d6198426a0549828a4e580cf8e3dcfa808
|
File details
Details for the file ztml-0.1.0-cp313-cp313-win_amd64.whl.
File metadata
- Download URL: ztml-0.1.0-cp313-cp313-win_amd64.whl
- Upload date:
- Size: 1.2 MB
- Tags: CPython 3.13, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27143f8d74d285680b953f76a8ffb05ad13ceeee77a50e7e27beb0cecea429d6
|
|
| MD5 |
46debc26f3bb5face8c98f151929cff1
|
|
| BLAKE2b-256 |
3fc851931f749ca5e403703dff2f7ca6c150a845bbbe9646d7f9768714347a51
|
File details
Details for the file ztml-0.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: ztml-0.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3f54089b15f4fe6bdd0a480020ea063bc90a098cde43945e6fbe9aabb601ab3e
|
|
| MD5 |
90633fa3f6a9213e9002fed4b4c471f5
|
|
| BLAKE2b-256 |
8083ce0b561ef06d51703c2b2508b1e30e93b8259f0e42137b79736cbc18aea8
|
File details
Details for the file ztml-0.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: ztml-0.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1bfa01d12c2d2d1f2135edda2df7f82e5f00f05dd47449b7a516ef70c3ed2d1
|
|
| MD5 |
ff80b21bd2018c89cfc7f7ce712afe80
|
|
| BLAKE2b-256 |
bb57ce0ea38d9f5dd033efb4c94f5801915ddadab0bbf6e3fefb9f27e539b9b3
|
File details
Details for the file ztml-0.1.0-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: ztml-0.1.0-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c58911ea8b728eecb08e85d35c5b8c15dc93a10745a537e0983d276c7090542
|
|
| MD5 |
678b114a395d4fbd4bfed24a4c181617
|
|
| BLAKE2b-256 |
37fc4f2cd3d525994fbca65b9da612a00199916d32009cbc71fdd6f4b6418593
|
File details
Details for the file ztml-0.1.0-cp313-cp313-macosx_10_12_x86_64.whl.
File metadata
- Download URL: ztml-0.1.0-cp313-cp313-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.13, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e10766de3e3dfe2e5c169d36382b848bfeb6a6a6373a929b3c2768d09b59acb0
|
|
| MD5 |
a03f38af70cb59a58c01b7e1046e7e3f
|
|
| BLAKE2b-256 |
63e4026470f8ccc5d5a3bbadbc11a611c59e2e248a1ee6258572833ccef6df00
|
File details
Details for the file ztml-0.1.0-cp312-cp312-win_amd64.whl.
File metadata
- Download URL: ztml-0.1.0-cp312-cp312-win_amd64.whl
- Upload date:
- Size: 1.2 MB
- Tags: CPython 3.12, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
84a51cb7f020ee016508f0f1dd2bccbfa9e68d676bed27c1ee8f61fd44dcb87e
|
|
| MD5 |
da77da1a394046fdf65bb06708200d51
|
|
| BLAKE2b-256 |
df04661150f846ef58fb58832019e231bf0638fff1264cbb5da4f5a53ec67bf6
|
File details
Details for the file ztml-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: ztml-0.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e9fde366d2b8c0491cf06a89de33c4b498e3e4908cafe2e3134a07b1746dd37f
|
|
| MD5 |
53c7939645dce6cc4833113f5061394a
|
|
| BLAKE2b-256 |
4c6cbc1e429e794335027e4f0332a6409a71676c3650ab7373189357c68e5e14
|
File details
Details for the file ztml-0.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: ztml-0.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 1.7 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f471e701e0d00f74b48737e95f1cd708e26e125294965382842aec927c50f978
|
|
| MD5 |
bacba3d0910b1c283497e43c13c45f98
|
|
| BLAKE2b-256 |
13913f0bbb5c5f463cb4d01ee3aab72e0ef6b89abffce86c62bc3abc9c40d0d5
|
File details
Details for the file ztml-0.1.0-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: ztml-0.1.0-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf630b8b17c47a12da888ab3ed68b7bafe8b23cd998b63fd29080239ef93990c
|
|
| MD5 |
609cd7dceda571e75742343e3e19e9a0
|
|
| BLAKE2b-256 |
8b0b78a170a6d457bb2a2ee3d4f4dc9653ece61694ce150cc9036a2a79a1befa
|
File details
Details for the file ztml-0.1.0-cp312-cp312-macosx_10_12_x86_64.whl.
File metadata
- Download URL: ztml-0.1.0-cp312-cp312-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.12, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f786867734fbe13483146e5dbe1ec76200cbe39e29bff6146daf3e0dec616098
|
|
| MD5 |
876aa022443a5df69b2d656b99345868
|
|
| BLAKE2b-256 |
6fcdc9b4a3c20e1cc5bfdc2a08d44386210336c747c4a0318fe599e108c8e283
|