Build static sites with Python.
Skip the template languages. Write pages as pure Python functions, generate optimized HTML, and deploy anywhere.
$ pip install nitro-clifrom nitro_ui import Body, Div, H1, H2, Paragraph, Section
from nitro import Page
FEATURES = [
("No templates", "Pages are Python functions."),
("No config", "Sensible defaults, zero setup."),
]
def render():
return Page(
title="Hello",
content=Body(
H1("Hello, World!"),
Section(
*[
Div(H2(name), Paragraph(text), cls="card")
for name, text in FEATURES
],
cls="features",
),
),
)<!doctype html>
<html>
<body>
<h1>Hello, World!</h1>
<section class="features">
<div class="card">
<h2>No templates</h2>
<p>Pages are Python functions.</p>
</div>
<div class="card">
<h2>No config</h2>
<p>Sensible defaults, zero setup.</p>
</div>
</section>
</body>
</html>Six Tools. One Ecosystem.
Install only what you need. Each package works standalone or together with the rest.
Build static sites with Python code instead of template engines. Live reload, incremental builds, deploy anywhere.
Create HTML with Python classes instead of strings. Type-safe, autocomplete-friendly, zero dependencies.
Access JSON with simple dot notation. No schemas to define - just load your data and go.
Add plugins to any Python app. Async-ready hooks with priorities and error isolation built in.
Validate data in one line. 51+ built-in rules, zero dependencies, clean pipe syntax.
Resize, convert, and optimize images with a chainable API. Generate responsive sizes in one call.
Three concepts.
Three concepts. That's it. No build configs, no magic - just Python you already know.
def render():
return Page(
title="Hello",
content=Body(H1("Hello, World!")),
)Pages are functions.
Each page is a Python function. Use variables, loops, conditionals - real code, not a template language.
Card(
H2("Welcome"),
Paragraph("Get started in seconds."),
cls="hero-card"
)Components are classes.
HTML elements are Python classes. Nest them, reuse them, pass data as keyword arguments.
data = DataStore.from_file("posts.json")
for post in data.posts:
Card(title=post.title)Data is dot notation.
Load JSON or YAML and access it with dots. No schemas, no boilerplate - just data.field.value.
Scaffold, watch, build.
Live reload while you work, incremental builds that skip what has not changed, and a plain folder of HTML at the end.
"Python is all you need."
No webpack. No template languages. No JavaScript required. Just Python functions that return HTML.
View on GitHub