Type-safe, composable UI components for Python — server-side rendered, HTMX-first.
Project description
htmforge
Type-safe, composable UI components for Python. Server-side rendered, HTMX-first, framework-agnostic.
Why htmforge?
- Type-safe props via Pydantic v2: props are validated on construction and on assignment.
- Small Element primitives with safe rendering:
Element.to_html()escapes text and maps Python attrs to HTML (e.g.cls→class). - First-class HTMX support: typed enums and helpers for
hx-*attrs. - Framework adapters:
to_fastapi(),to_flask(),to_django()on components for easy integration.
Installation
pip install htmforge
Quickstart (Flask)
Copy-pasteable minimal Flask example using a Page and a DataTable.
from flask import Flask
from htmforge.components.page import Page
from htmforge.components import DataTable
from htmforge.core.element import Element
from htmforge.elements import div, h1
app = Flask(__name__)
class UsersPage(Page):
users: list[list[str]]
def _body_content(self) -> list[Element | str | None]:
return [
div(
h1("Users"),
DataTable(headers=["Name", "Email"], rows=self.users),
)
]
@app.route("/users")
def users():
rows = [["Ada Lovelace", "ada@example.com"]]
return UsersPage(title="Users", users=rows).to_flask()
if __name__ == "__main__":
app.run(debug=True)
Elements
htmforge.elements exposes small factory functions for HTML tags. These
map Pythonic attribute names to HTML and escape text safely. Example:
from htmforge.elements import div, span, input
el = div(
span("Name:"),
input(type="search", name="q", hx_get="/search", cls="search"),
cls="form-row",
)
print(el.to_html())
The hx_get argument renders as hx-get, and text is escaped by
default to prevent XSS.
Components
| Component | Description | Import |
|---|---|---|
| Alert | Dismissible info/success/warning/error box | from htmforge.components import Alert |
| Badge | Small inline label with variant classes | from htmforge.components import Badge |
| Breadcrumb | Ordered nav with aria-current for current item |
from htmforge.components import Breadcrumb |
| DataTable | Table with optional HTMX reloading | from htmforge.components import DataTable |
| FormField | Label + input + optional error block | from htmforge.components import FormField |
| Modal | Trigger button + <dialog> overlay (HTMX body) |
from htmforge.components import Modal |
| Page | Abstract full-page component (adds DOCTYPE) | from htmforge.components.page import Page |
| Pagination | Page links + prev/next, supports HTMX targets | from htmforge.components import Pagination |
| SearchInput | Search input with keyup debounce via HTMX |
from htmforge.components import SearchInput |
HTMX integration
Typed enums live in htmforge.htmx: HxSwap, HxTrigger, HxTarget,
and HxPushUrl. They render the correct attribute values. Example:
from htmforge.elements import button
from htmforge.htmx import HxSwap, HxTarget
btn = button(
"Delete",
hx_delete="/items/1",
hx_swap=HxSwap.OUTER_HTML,
hx_target=HxTarget.CLOSEST_TR,
)
Use hx_keyup_delay(ms) to produce keyup delay:{ms}ms trigger strings
for debounced search inputs.
Framework support
FastAPI example:
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.get("/", response_class=HTMLResponse)
def index():
return UsersPage(title="Home").to_html()
Flask example (adapter shown above uses to_flask()):
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return UsersPage(title="Home").to_flask()
Django example:
def index(request):
return UsersPage(title="Home").to_django()
License
This project is licensed under the MIT License with the Commons Clause
condition. It is free for personal projects, open source projects, and
small businesses (see LICENSE). Organizations with annual revenue or
funding over USD 1,000,000 or more than 100 employees require a
separate commercial license from the author.
Contributing
See CONTRIBUTING.md and the docs site at
https://mondi04.github.io/htmforge/ for contribution guidelines.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
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 htmforge-0.2.1.tar.gz.
File metadata
- Download URL: htmforge-0.2.1.tar.gz
- Upload date:
- Size: 2.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9af5701ef97800ee0bca9c1429c141eabce433b903efa30cf33bd58efc966cb5
|
|
| MD5 |
87e706938b4ecc02766699194ab08fb3
|
|
| BLAKE2b-256 |
c315fd88aa60362b389ce540bceb48965f86460c834d6d4ea4c9897d27b7a9f0
|
File details
Details for the file htmforge-0.2.1-py3-none-any.whl.
File metadata
- Download URL: htmforge-0.2.1-py3-none-any.whl
- Upload date:
- Size: 27.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d04a3cf2a0ad0dc7aa4afa15e9e942b528d7208dcb5e110851f8b24aaccf241
|
|
| MD5 |
a914f3e19ddbfe902400892e8bf0a4df
|
|
| BLAKE2b-256 |
97aa09bd3541ee4aacc410bcfdde7e33740c161a0ecd9c275904d6ff2bc7db68
|