Backend-neutral Hyper HTML templates for Python
Project description
Hyper
Write type-safe HTML in .hyper files. Import components directly from Python.
uv add hyperhtml
Requires Python 3.10 or newer.
Create a component
Create app/pages/Greeting.hyper:
<h1>Hello, World!</h1>
Import and call it:
from app.pages import Greeting
print(Greeting())
<h1>Hello, World!</h1>
The filename becomes the component name. Hyper compiles it on first import.
Pass data
Add typed props above ---:
name: str
---
<h1>Hello, {name}!</h1>
print(Greeting(name="Ada"))
<h1>Hello, Ada!</h1>
Props are keyword-only. Values are escaped by default.
Add a nested component
Use component for reusable markup inside the file:
# app/pages/Dashboard.hyper
title: str
---
component Header(*, title: str):
<header><h1>{title}</h1></header>
end
<{Header} title={title} />
The file exports Dashboard and its nested Header:
from app.pages import Dashboard
Dashboard(title="Account")
Dashboard.Header(title="Account")
Both calls return:
<header><h1>Account</h1></header>
Dashboard("Account") raises TypeError because props are keyword-only.
Pass content
Place {...} where caller content belongs:
# app/components/Card.hyper
title: str
---
<article>
<h2>{title}</h2>
<main>{...}</main>
</article>
Pass content between component tags:
# app/pages/Confirm.hyper
from app.components import Card
---
<{Card} title="Delete item">
<p>This cannot be undone.</p>
</{Card}>
<article><h2>Delete item</h2><main><p>This cannot be undone.</p></main></article>
Group components in one file
A file with declarations and no rendered output is a component library:
# app/components/forms.hyper
component Button(*, label: str, **attrs):
<button {**attrs}>{label}</button>
end
component Input(*, name: str, type: str = "text"):
<input {name} {type} />
end
Import its components like a Python module:
from app.components.forms import Button, Input
Button(label="Save", disabled=True)
Input(name="email", type="email")
<button disabled>Save</button>
<input name="email" type="email">
Use Python
Python statements and expressions stay Python:
items: list[str]
show_count: bool = True
---
<ul>
for item in items:
<li>{item.upper()}</li>
end
</ul>
if show_count:
<p>{len(items)} items</p>
end
Imports, functions, classes, match, try, with, and async code use the same block form.
Split long tags
Formatting whitespace between attributes does not render:
<{Button}
label="Save"
class={["button", {"active": active}]}
hx-post="/save"
/>
Stream output
Calling a component joins its chunks. .stream() returns the generated iterator:
html = Feed(posts=posts)
chunks = Feed.stream(posts=posts)
from fastapi.responses import StreamingResponse
@app.get("/feed")
def feed():
return StreamingResponse(
Feed.stream(posts=posts),
media_type="text/html",
)
Use Django or Jinja
Django views can return a component directly:
from django.http import HttpResponse
def home(request):
return HttpResponse(Dashboard(title="Account"))
Jinja can discover .hyper files from its template paths:
env.add_extension("hyperhtml.integrations.jinja2.HyperExtension")
{{ Dashboard(title="Account") }}
See Integrations for Django templates, Jinja slots, Flask, Litestar, and Sanic.
How files import
.hyper file |
Python import |
|---|---|
Contains rendered output or --- |
Component named after the file |
| Contains declarations only | Normal module with exported names |
Has an adjacent .py file |
Python file wins |
Implicit file components must live inside a package. Root-level .hyper files can be component libraries.
IDE support
- JetBrains: syntax highlighting, Python language injection, and compiler diagnostics
- TextMate and VS Code: syntax highlighting
Documentation
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 hyperhtml-0.1.2.tar.gz.
File metadata
- Download URL: hyperhtml-0.1.2.tar.gz
- Upload date:
- Size: 151.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3818e1c59e286c49ea6274a59b8a48c20219819393647a96eca93cddb054f272
|
|
| MD5 |
0ed1df029b33c1dd17481daa36e38262
|
|
| BLAKE2b-256 |
9da195c2bb59eb5cc836fd8402d9506195d119cf20b4ca1158407f507957910b
|
File details
Details for the file hyperhtml-0.1.2-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: hyperhtml-0.1.2-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 449.0 kB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4fdb7aabd4b06db76a9f3d60163d24a3211e67126690f9f86c3fb74214c5eae
|
|
| MD5 |
5c78bd445afc4a3f030d63f64a419921
|
|
| BLAKE2b-256 |
389c83fd01a72c4e1d5d8d38e75e554350a2c6ac4ab140c3ab6eed489ed8eb01
|
File details
Details for the file hyperhtml-0.1.2-cp310-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: hyperhtml-0.1.2-cp310-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 573.3 kB
- Tags: CPython 3.10+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d1f20e5647709ccc1c642b3b4157ec81e689d35b93a9b4a32ef19dd2eb33d339
|
|
| MD5 |
b7cd83362692d7f66132f4acafd6b21a
|
|
| BLAKE2b-256 |
5eef49f93e599ef8b93701808be7c1279510439ef5e7b37d3901619eeedf3a4b
|
File details
Details for the file hyperhtml-0.1.2-cp310-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: hyperhtml-0.1.2-cp310-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 523.6 kB
- Tags: CPython 3.10+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
caa83782ea36b025a91deada4d3787ebcd3eeebc9a222423ad3c11e0bb8b1b8b
|
|
| MD5 |
d77b366a566e9b25c07449a11bfd7d5f
|
|
| BLAKE2b-256 |
6d0a9b82a8040b7fe121362da6c70929f9840bda48519d9869c0ab11458d5a87
|
File details
Details for the file hyperhtml-0.1.2-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: hyperhtml-0.1.2-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 502.7 kB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c39e5565968e96e7c6b4cb1a06182fa9d80774ba94632a38c26694c6c8d0146a
|
|
| MD5 |
3d1e0cb1c95cf28945597f15cde4d049
|
|
| BLAKE2b-256 |
725b49ab4aa3c7f127ad7db786ebd9b49bbd5cd4c778ae273b46c39fff1d8acf
|
File details
Details for the file hyperhtml-0.1.2-cp310-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: hyperhtml-0.1.2-cp310-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 522.3 kB
- Tags: CPython 3.10+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
66e85f1a603e8e35e0aa9685be2895d9958c564a4adf41fdb89bbd9279c5939e
|
|
| MD5 |
b38fd28cecfd253b1853c0937f442890
|
|
| BLAKE2b-256 |
d72bd80ebae673dd8bb7528ca7cde95463fff94a608194821e86ecbd1a6cda6d
|