Build HTML with Python, not strings. Zero-dependency library with type-safe elements, method chaining, and JSON serialization.
Project description
NitroUI
Build HTML with Python, not strings.
NitroUI is a zero-dependency Python library that lets you construct HTML documents using a clean, composable class-based API. No template files, no string concatenation, no runtime dependencies.
from nitro_ui import *
page = HTML(
Head(Title("Dashboard")),
Body(
Nav(
Link("Home", href="/"),
Link("Settings", href="/settings", class_name="active")
),
Main(
H1("Welcome back!"),
Div(
Paragraph("You have ", Strong("3"), " new notifications."),
Button("View All", type="button", class_name="btn-primary")
)
)
)
)
print(page.render(pretty=True))
Why NitroUI?
- Type-safe: IDE autocomplete and type hints for every element
- Composable: Build reusable components as Python classes
- Zero dependencies: Just Python 3.8+, nothing else
- Framework agnostic: Works with FastAPI, Django, Flask, or standalone
- Serializable: Convert to/from JSON for drag-and-drop builders
- LLM-friendly: Perfect for AI-generated interfaces
Installation
pip install nitro-ui
Claude Code Skill
Add NitroUI as a skill in Claude Code for AI-assisted HTML generation:
npx skills add nitrosh/nitro-ui
Quick Examples
HTML-like Syntax
Prefer lowercase tag names that look like real HTML? Use nitro_ui.html:
from nitro_ui.html import div, h1, p, ul, li, a, img
page = div(
h1("Welcome"),
p("This looks just like HTML!"),
ul(
li(a("Home", href="/")),
li(a("About", href="/about")),
),
img(src="hero.jpg", alt="Hero image"),
class_name="container"
)
All standard HTML tags are available as lowercase functions. Python keywords use a trailing underscore: del_, input_, object_, map_.
Dynamic Content
from nitro_ui import *
def render_user_card(user):
return Div(
Image(src=user["avatar"], alt=user["name"]),
H3(user["name"]),
Paragraph(user["bio"]),
Link("View Profile", href=f"/users/{user['id']}"),
class_name="user-card"
)
users = [
{"id": 1, "name": "Alice", "bio": "Backend engineer", "avatar": "/avatars/alice.jpg"},
{"id": 2, "name": "Bob", "bio": "Frontend developer", "avatar": "/avatars/bob.jpg"},
]
grid = Div(*[render_user_card(u) for u in users], class_name="user-grid")
Method Chaining
from nitro_ui import *
card = (Div()
.add_attribute("id", "hero")
.add_styles({"background": "linear-gradient(135deg, #667eea 0%, #764ba2 100%)", "padding": "4rem"})
.append(H1("Ship faster with NitroUI"))
.append(Paragraph("Stop fighting with templates. Start building.")))
Reusable Components
from nitro_ui import *
class Card(HTMLElement):
def __init__(self, title, *children, **kwargs):
super().__init__(**{**kwargs, "tag": "div"})
self.add_attribute("class", "card")
self.append(H3(title, class_name="card-title"))
for child in children:
self.append(child)
class Alert(HTMLElement):
def __init__(self, message, variant="info", **kwargs):
super().__init__(**{**kwargs, "tag": "div"})
self.add_attributes([("class", f"alert alert-{variant}"), ("role", "alert")])
self.append(Paragraph(message))
# Usage
page = Div(
Alert("Your changes have been saved.", variant="success"),
Card("Statistics",
Paragraph("Total users: 1,234"),
Paragraph("Active today: 89")
)
)
External Stylesheets with Themes
from nitro_ui import *
from nitro_ui.styles import CSSStyle, StyleSheet, Theme
# Use a preset theme
theme = Theme.modern()
stylesheet = StyleSheet(theme=theme)
# Register component styles
btn = stylesheet.register("btn", CSSStyle(
background_color="var(--color-primary)",
color="var(--color-white)",
padding="var(--spacing-sm) var(--spacing-md)",
border_radius="6px",
border="none",
cursor="pointer",
_hover=CSSStyle(background_color="var(--color-primary-dark)")
))
# Use in your HTML
page = HTML(
Head(
Title("Styled Page"),
Style(stylesheet.render())
),
Body(
Button("Click Me", class_name=btn)
)
)
Framework Integration
FastAPI
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from nitro_ui import *
app = FastAPI()
@app.get("/", response_class=HTMLResponse)
async def home():
return HTML(
Head(Title("FastAPI + NitroUI")),
Body(H1("Hello from FastAPI"))
).render()
Flask
from flask import Flask
from nitro_ui import *
app = Flask(__name__)
@app.route("/")
def home():
return HTML(
Head(Title("Flask + NitroUI")),
Body(H1("Hello from Flask"))
).render()
Django
from django.http import HttpResponse
from nitro_ui import *
def home(request):
return HttpResponse(HTML(
Head(Title("Django + NitroUI")),
Body(H1("Hello from Django"))
).render())
Core Features
Pretty Printing
# Compact output (default) - ideal for production
page.render()
# Indented output - ideal for debugging
page.render(pretty=True)
JSON Serialization
Perfect for drag-and-drop builders, undo/redo, or API communication:
from nitro_ui import *
from nitro_ui.core.element import HTMLElement
# Serialize
json_data = page.to_json(indent=2)
# Deserialize
restored = HTMLElement.from_json(json_data)
HTML Parsing
Import existing HTML into NitroUI for manipulation:
from nitro_ui import from_html
element = from_html('<div class="card"><h1>Hello</h1></div>')
element.append(Paragraph("Added with NitroUI"))
Fragments
Group elements without a wrapper tag:
from nitro_ui import *
def table_rows(items):
return Fragment(*[
TableRow(TableDataCell(item["name"]), TableDataCell(item["price"]))
for item in items
])
CSS Style Helpers
div = Div("Content")
div.add_style("color", "blue")
div.add_styles({"padding": "20px", "margin": "10px"})
div.remove_style("margin")
color = div.get_style("color") # "blue"
Available Elements
PascalCase imports (from nitro_ui import *):
| Module | Elements |
|---|---|
nitro_ui.tags.html |
HTML, Head, Body, Title, Meta, Script, Style, HtmlLink, IFrame |
nitro_ui.tags.layout |
Div, Section, Article, Header, Nav, Footer, Main, Aside, Dialog |
nitro_ui.tags.text |
H1-H6, Paragraph, Span, Strong, Em, Link, Code, Pre, Blockquote |
nitro_ui.tags.form |
Form, Input, Button, Select, Option, Textarea, Label, Fieldset |
nitro_ui.tags.lists |
UnorderedList, OrderedList, ListItem, DescriptionList |
nitro_ui.tags.media |
Image, Video, Audio, Figure, Canvas, Picture, Source |
nitro_ui.tags.table |
Table, TableRow, TableHeader, TableBody, TableHeaderCell, TableDataCell |
Lowercase HTML-like imports (from nitro_ui.html import *):
| Category | Aliases |
|---|---|
| Document | html, head, body, title, meta, script, style, link |
| Layout | div, section, article, header, nav, footer, main, hr |
| Text | h1-h6, p, span, strong, em, a, code, pre, b, i |
| Form | form, input_, button, select, option, textarea, label |
| Lists | ul, ol, li, dl, dt, dd |
| Media | img, video, audio, figure, canvas, picture, source |
| Table | table, tr, td, th, thead, tbody, tfoot |
Note: input_, del_, object_, map_ use trailing underscore to avoid Python keyword/builtin conflicts.
Element API
Manipulation
append(*children)/prepend(*children)- Add childrenclear()- Remove all childrenclone()- Deep copy elementfind_by_attribute(attr, value)- Find child by attribute
Attributes
add_attribute(key, value)/add_attributes(list)get_attribute(key)/has_attribute(key)remove_attribute(key)
Styles
add_style(prop, value)/add_styles(dict)get_style(prop)/remove_style(prop)
Output
render(pretty=False)- Generate HTML stringto_json()/from_json()- JSON serializationto_dict()/from_dict()- Dictionary conversion
All manipulation methods return self for chaining.
For AI/LLM Integration
NitroUI is designed to work seamlessly with AI code generation. See LLM_GUIDE.md for a complete technical reference including exact method signatures, type hints, and common patterns.
Development
# Setup
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
# Run tests
pytest
# Format
black src/ tests/
License
BSD 3-Clause License. See LICENSE for details.
Links
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 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 nitro_ui-1.0.3.tar.gz.
File metadata
- Download URL: nitro_ui-1.0.3.tar.gz
- Upload date:
- Size: 51.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fff9ea1902db1dea0ad9c05e401dad17ca44e7006819d05294c9528d1d4f4e5d
|
|
| MD5 |
8931b54ddb1e6c2f88e87257ad4de3d2
|
|
| BLAKE2b-256 |
5a0094da363f080e76ea485a0c83ef31a0c983c798a73223e6fd41bbd4f3f48e
|
File details
Details for the file nitro_ui-1.0.3-py3-none-any.whl.
File metadata
- Download URL: nitro_ui-1.0.3-py3-none-any.whl
- Upload date:
- Size: 31.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a60f21e705880e24955bfa80ef45fb7a60d7624613fbcc86852f7581e3d204b3
|
|
| MD5 |
f061426fe8493b4d27a41d0400466256
|
|
| BLAKE2b-256 |
713f4eec154cce699a3c4f662573d880876c2c09eb760a64381537892b53a9da
|