Skip to content

scriptogre/hyper

Repository files navigation

Hyper

CI License: MIT

Type-safe templates for Python, powered by Rust.

uvx hyper .

.hyper files compile to Python components with slots, type-safe arguments, and full IDE support.

Quick Start

1. Write a template. Props go above the ---, template body below.

# app/components/Greeting.hyper

name: str

---

<h1>Hello, {name}!</h1>

2. Compile it.

uvx hyper .
# ✓ app/components/Greeting.py

3. Use it.

from app.components import Greeting

@app.get("/", response_class=HTMLResponse)
def index():
    return Greeting(name="World")

Features

Components

Components compose like HTML elements. Children go in the default slot with {...}.

# app/components/ProductCard.hyper

name: str
price: float
image: str
on_sale: bool = False

---

<div class={["card", {"sale": on_sale}]}>
    <img src={image} alt={name} />
    <h3>{name}</h3>
    if on_sale:
        <span class="badge">Sale</span>
    end
    <p class="price">${price:.2f}</p>
</div>
# app/pages/Store.hyper
from app.layouts import Layout
from app.components import ProductCard

products: list[Product]

---

<{Layout} title="Store">
    for product in products:
        <{ProductCard}
            name={product.name}
            price={product.price}
            image={product.image}
            on_sale={product.on_sale}
        />
    end
</{Layout}>

Control flow

The template body is the function body. Any valid Python works. Blocks end with end.

from app.enums import Status
from app.models import Product

status: Status
products: list[Product]

---

match status:
    case Status.LOADING:
        <div class="spinner" />
    case Status.ERROR:
        <p class="error">Something went wrong</p>
    case Status.OK:
        if not products:
            <p>No products found</p>
        else:
            <ul>
                for product in products:
                    <li>{product.name}</li>
                end
            </ul>
        end
end

Streaming

Every component is a generator, so streaming works out of the box:

from fastapi.responses import StreamingResponse
from app.pages import Store

@app.get("/store")
def store():
    return StreamingResponse(Store(products=products), media_type="text/html")

IDE Support

  • JetBrains (PyCharm, IntelliJ) — Full Python intelligence inside .hyper files: autocomplete, go-to-definition, type checking, auto-transpilation on save
  • TextMate / VS Code — Syntax highlighting

Acknowledgements

Hyper's component and attribute syntax was inspired by tdom.

Contributing

See CONTRIBUTING.md.

License

MIT

About

Type-safe templates for Python, powered by Rust.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors