Skip to main content

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.

Custom Components

Any Python object with a __ztml_render__ method can be used as a renderable component. The method should return a ztml element.

class Card:
    def __init__(self, title, body):
        self.title = title
        self.body = body

    def __ztml_render__(self):
        return Div(
            H2(self.title),
            P(self.body),
        ).cls("card")

# Use directly in render()
print(render(Card("Hello", "World")))

# Or nest inside other elements
page = Div(
    Card("First", "Some content"),
    Card("Second", "More content"),
).cls("cards")

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}') extracts name as a function argument
  • Request access — add a request parameter to access the Starlette Request object
  • 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

# Custom components demo
uv run examples/components.py > components.html

# HTMX todo app (localhost:5001)
uv run examples/todo_server.py

Running Tests

uv run python -m 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, and Frame
  • Enum classes — for CSS keyword values and HTML attribute values

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ztml-0.1.1-cp314-cp314-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.14Windows x86-64

ztml-0.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

ztml-0.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ ARM64

ztml-0.1.1-cp314-cp314-macosx_11_0_arm64.whl (1.4 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

ztml-0.1.1-cp314-cp314-macosx_10_12_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.14macOS 10.12+ x86-64

ztml-0.1.1-cp313-cp313-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.13Windows x86-64

ztml-0.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

ztml-0.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ ARM64

ztml-0.1.1-cp313-cp313-macosx_11_0_arm64.whl (1.4 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

ztml-0.1.1-cp313-cp313-macosx_10_12_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.13macOS 10.12+ x86-64

ztml-0.1.1-cp312-cp312-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.12Windows x86-64

ztml-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

ztml-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.6 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

ztml-0.1.1-cp312-cp312-macosx_11_0_arm64.whl (1.4 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

ztml-0.1.1-cp312-cp312-macosx_10_12_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.12macOS 10.12+ x86-64

File details

Details for the file ztml-0.1.1-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: ztml-0.1.1-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: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ztml-0.1.1-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 3601e13574c40f7b98c11998f09147e700309925e345823a9a3ad545ecf051ce
MD5 82f34261efed713705fa3bafd4f78f83
BLAKE2b-256 9bb6de7a65dfe0499759bf7bc01b6af6d28f3c169fa5f36b2a64e3338c3add29

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp314-cp314-win_amd64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 5639dbf6c80ba1e5f3aca549814eaba1e464c189a0ad9f668b629dbccb0eed50
MD5 a378e6b6a7401daf82cb816f1b7cac54
BLAKE2b-256 e5441461d69dd50a0590973fc795177b332d825f243fc803731487b69100825c

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 41867e6fbfb436a75725967cbbac4be63450e24693f4d564ae9d0975f612ed06
MD5 9ca961acc5285553f9d3c4e45b84af10
BLAKE2b-256 90814a90a8c5527fd974671ad8ceb8b915734cdcffba23bd1c3d99dd56cd9e73

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ae5fdb0b2ce4bbf5e36bea4f221d6de8d9579b09edbf0b9d477d17e23867ff0c
MD5 27037a6722a6a491f2556c93a6dc26a3
BLAKE2b-256 8ada36937e86d9791dbebe5fc34d9ca578f7f933b3e42e112a07e0dbbef17cde

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp314-cp314-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp314-cp314-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 25b4e4bc0cce0665452bf6b745512f472d2caadc9afbd58ac7293c2bae5e359a
MD5 b7ba16a66eea54d0966ca16d34266b2e
BLAKE2b-256 9c0c914fd07ae42d93217f7e1fb847be3df353ebac474f7a36d311d7ea0d839c

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp314-cp314-macosx_10_12_x86_64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: ztml-0.1.1-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: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ztml-0.1.1-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 1f2d4845e52cbca6cbb5f4af238e857aae335a7ed9e2f1935862b61d8778f717
MD5 834aad5607952cc9edc1e47f8de702b6
BLAKE2b-256 ba98d795955d8ddc055efab581509deac1d3be6522c228839ca12be969428e2c

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp313-cp313-win_amd64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7612ad5609548724ec133b97f22d00e7636310ed45fffa5cb33af648456ea1b8
MD5 3e63ce349d141e9e2494c364700115fb
BLAKE2b-256 ca28bec51527872c0e5e03b4ff6bc2f3b7214154ed9ff4335354b986a6204ba0

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 e20750ebc4d7117baa3fd55eecdab847cec1d89356c1aa8940768165b37095ff
MD5 0feda33a4902768c2fdd0a8ec0015779
BLAKE2b-256 ac7d1f26327dfa6d7d3398c6adf51b3b91c0b57b88dfd06b0e266723855b097a

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c1e89bb4cda162c615ecac57a6dc720ef0a7d45e8e8e2ab05bc1d14975836008
MD5 4a0e02a0da84e600fdbf2effd3e3ed83
BLAKE2b-256 b7edca4af1fffe8b21b4f0359f1fd8895e73ae802318faf6f8a79aafbbf232dc

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp313-cp313-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 8d21ea49ad2d6799da62a16fe45c04408d1cf16e27dcecbd8db991ee40277d85
MD5 b86a145cc7324bb3d759445144b4fc1e
BLAKE2b-256 308418b4229346928a1523f04e7b89db977b9adbb34228814f0ab6d81501e1e1

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp313-cp313-macosx_10_12_x86_64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: ztml-0.1.1-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: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ztml-0.1.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 0807137cc4e121604e7d8031d8be890903d37f3144f10affc294575463172462
MD5 d846c8299adc6f59a3b8269d56ff93a3
BLAKE2b-256 225ca6c01259a7cace5e57fb9130f9259beb1c8e624b0ef8874c60ca3bf271a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp312-cp312-win_amd64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b3fad08c35d47f1800ab6fe3c207c865f75eb1399126ed907bd607de9f3830d9
MD5 3dfbc23d6fc701bcab3d09bb4afeea90
BLAKE2b-256 738acfc311bcd3719f84bc81e3530116ea58139c64940aaeb5af6d505f19cc94

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 30a4db1b17beaff1305624e914d07c3e5c0056bb9f52bed172f375e6975e1905
MD5 5b92b3dd3ae09e9e3071aef323be7af6
BLAKE2b-256 8028f2e97d50fe09994ec1b1b3485d0b3906c973e5b5d88afeb0fedb0c324781

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8f2c0718f0b39e990cd875f2693307e7f3c85bf24249b9b7891a9bd1a055dcfc
MD5 dd407474f8a215526013aa7a8f5b4ba1
BLAKE2b-256 8fc807caaed391ea1ad9a75e50472f9c61f7df9d740c2d0ec81f48f517f6a127

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ztml-0.1.1-cp312-cp312-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for ztml-0.1.1-cp312-cp312-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 b5ed7eff3be47859ff107f30796373ef6db081cd7bb19a6cb941bf899e521d45
MD5 41951185bc566ff222a7910d9294d3d2
BLAKE2b-256 e96c5020f388b8b14596ad09b8d1da6de6b2ec300bb83bbbb6de7574795f7dea

See more details on using hashes here.

Provenance

The following attestation bundles were made for ztml-0.1.1-cp312-cp312-macosx_10_12_x86_64.whl:

Publisher: ci.yml on bleemesser/ztml

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page