StructFlow
A modern, type-safe Python library for generating HTML documents programmatically. StructFlow provides a clean, Pythonic API for creating HTML with full type hints and comprehensive tag support.
Features
- Type-safe: Full type hints with mypy support
- Complete HTML5 support: All standard HTML5 elements and attributes
- Clean API: Intuitive, Pythonic interface
- Flexible rendering: Pretty-printing and minified output options
- XHTML support: Optional XHTML-compliant output
- Extensible: Easy to extend with custom elements and attributes
Installation
pip install structflow
Or with Poetry:
poetry add structflow
Quick Start
from structflow import Document
from structflow.tags import div, h1, p, a, title, meta
# Create a document with head elements
doc = Document(
title("My Page Title"),
meta(charset="utf-8"),
meta(name="viewport", content="width=device-width, initial-scale=1"),
html_lang="en"
)
# Add content to body
doc.add(
div(
h1("Welcome to StructFlow", class_="hero-title"),
p("A modern HTML generation library for Python."),
a("Learn more", href="https://example.com", class_="btn btn-primary")
)
)
# Render the document
html_output = doc.render()
print(html_output)
Core Concepts
Document Structure
The Document class serves as the root container for your HTML document. Head elements are passed directly to the constructor:
from structflow import Document
from structflow.tags import title, meta, link
doc = Document(
# Head elements passed directly
title("Page Title"),
meta(charset="utf-8"),
meta(name="viewport", content="width=device-width, initial-scale=1"),
link(rel="stylesheet", href="styles.css"),
# Document options
doctype="<!DOCTYPE html>",
html_lang="en",
html_dir="ltr",
pretty=True,
xhtml=False
)
Adding Content
Head elements are specified in the document constructor, while body content is added using the add() method:
from structflow.tags import title, meta, link, div, h1
# Create document with head elements
doc = Document(
title("Page Title"),
meta(charset="utf-8"),
link(rel="stylesheet", href="styles.css")
)
# Add body content
doc.add(
div(
h1("Hello World"),
class_="container"
)
)
HTML Elements
All HTML5 elements are available as classes with proper typing:
from structflow.tags import (
# Structure
div, span, section, article, nav, aside, header, footer, main,
# Text content
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
# Lists
ul, ol, li, dl, dt, dd,
# Forms
form, input, textarea, select, option, button, label,
# Media
img, video, audio, source, picture,
# Tables
table, thead, tbody, tfoot, tr, th, td,
# Head elements
title, meta, link, script, style, base,
# And many more...
)
Attributes
All elements support both common HTML attributes and element-specific ones:
# Common attributes
div(id_="main", class_="container", style="color: blue;")
# Element-specific attributes
img(src="image.jpg", alt="Description", width=300, height=200)
input(type="email", name="email", required=True, placeholder="Enter email")
a(href="https://example.com", target="_blank", rel="noopener")
Class Attribute Handling
The class_ parameter accepts both strings and lists:
# String
div(class_="btn btn-primary")
# List (automatically joined with spaces)
div(class_=["btn", "btn-primary", "btn-large"])
Advanced Usage
Head Elements
StructFlow provides comprehensive support for all head elements with proper typing:
from structflow.tags import title, meta, link, script, style
doc = Document(
# Page metadata
title("My Application"),
meta(charset="utf-8"),
meta(name="description", content="A great web application"),
meta(name="keywords", content="python, html, web"),
meta(name="author", content="Your Name"),
# Viewport for responsive design
meta(name="viewport", content="width=device-width, initial-scale=1"),
# Open Graph metadata
meta(property="og:title", content="My Application"),
meta(property="og:description", content="A great web application"),
meta(property="og:image", content="https://example.com/image.jpg"),
# External resources
link(rel="stylesheet", href="styles.css"),
link(rel="icon", href="favicon.ico", type="image/x-icon"),
link(rel="preconnect", href="https://fonts.googleapis.com"),
# Scripts
script(src="https://cdn.example.com/library.js", defer=True),
# Inline styles
style("""
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
"""),
html_lang="en"
)
Custom Attributes
Use **kwargs for custom or non-standard attributes:
div(
"Content",
data_id="123",
data_toggle="modal",
aria_label="Close button"
)
Nested Elements
Elements can be deeply nested:
nav(
div(
ul(
li(a("Home", href="/")),
li(a("About", href="/about")),
li(a("Contact", href="/contact"))
),
class_="navbar-nav"
),
class_="navbar"
)
Forms
Creating forms with proper structure:
form(
fieldset(
legend("Contact Information"),
div(
label("Name:", for_="name"),
input(type="text", id_="name", name="name", required=True),
class_="form-group"
),
div(
label("Email:", for_="email"),
input(type="email", id_="email", name="email", required=True),
class_="form-group"
),
button("Submit", type="submit", class_="btn btn-primary")
),
action="/submit",
method="post"
)
Tables
Building data tables:
table(
thead(
tr(
th("Name"),
th("Age"),
th("City")
)
),
tbody(
tr(
td("John Doe"),
td("30"),
td("New York")
),
tr(
td("Jane Smith"),
td("25"),
td("Los Angeles")
)
),
class_="data-table"
)
Media Elements
Working with images and multimedia:
# Responsive image
picture(
source(
srcset="image-large.jpg",
media="(min-width: 800px)"
),
source(
srcset="image-medium.jpg",
media="(min-width: 400px)"
),
img(
src="image-small.jpg",
alt="Responsive image",
class_="responsive-img"
)
)
# Video with multiple sources
video(
source(src="video.mp4", type="video/mp4"),
source(src="video.webm", type="video/webm"),
"Your browser doesn't support video.",
controls=True,
width=640,
height=480
)
Rendering Options
Pretty Printing
Enable pretty printing for readable output:
doc = Document(pretty=True)
# or
html_output = doc.render(pretty=True)
XHTML Mode
Generate XHTML-compliant output:
doc = Document(xhtml=True)
# or
html_output = doc.render(xhtml=True)
Custom Doctype
Specify a custom doctype:
doc = Document(doctype="<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"")
Complete Example
Here's a comprehensive example showing a complete HTML document:
from structflow import Document
from structflow.tags import *
# Create document with comprehensive head
doc = Document(
# Basic metadata
title("StructFlow Demo - Modern HTML Generation"),
meta(charset="utf-8"),
meta(name="viewport", content="width=device-width, initial-scale=1"),
meta(name="description", content="Demo of StructFlow HTML generation"),
# External resources
link(rel="stylesheet", href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"),
link(rel="icon", href="favicon.ico"),
# Custom styles
style("""
.hero { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); }
.hero h1 { color: white; }
"""),
html_lang="en"
)
# Build the page content
doc.add(
header(
nav(
div(
a("StructFlow", href="#", class_="navbar-brand"),
ul(
li(a("Home", href="#", class_="nav-link"), class_="nav-item"),
li(a("Docs", href="#", class_="nav-link"), class_="nav-item"),
li(a("GitHub", href="#", class_="nav-link"), class_="nav-item"),
class_="navbar-nav ms-auto"
),
class_="container-fluid"
),
class_="navbar navbar-expand-lg navbar-dark bg-dark"
)
),
main(
section(
div(
div(
div(
h1("Modern HTML Generation", class_="display-4"),
p("Build HTML documents with Python using a clean, type-safe API.",
class_="lead"),
a("Get Started", href="#features", class_="btn btn-light btn-lg"),
class_="col-md-8"
),
class_="row justify-content-center text-center"
),
class_="container py-5"
),
class_="hero py-5"
),
section(
div(
h2("Features", class_="text-center mb-5"),
div(
div(
div(
h3("Type Safe"),
p("Full type hints with mypy support for error-free development."),
class_="card-body"
),
class_="card h-100"
),
div(
div(
h3("Modern API"),
p("Clean, Pythonic interface that feels natural to use."),
class_="card-body"
),
class_="card h-100"
),
div(
div(
h3("Complete"),
p("All HTML5 elements and attributes with proper validation."),
class_="card-body"
),
class_="card h-100"
),
class_="row g-4"
),
class_="container py-5"
),
id_="features"
)
),
footer(
div(
p("© 2025 StructFlow. Built with ❤️ and Python.",
class_="text-center text-muted"),
class_="container py-4"
),
class_="bg-light mt-5"
),
# Bootstrap JavaScript
script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js")
)
# Render the complete document
html_output = doc.render()
Tag Categories
The library organizes tags into logical modules:
head:title,meta,link,script,style,base,noscript,templateedits:ins,del_embedded:img,video,audio,embed,iframe,object,canvas,svgforms:form,input,textarea,select,button,fieldset, etc.grouping:div,p,hr,ul,ol,li,dl,dt,dd, etc.links:a,areascripting:script,noscript,templatesections:section,article,nav,aside,header,footer,maintable:table,thead,tbody,tr,th,td, etc.text:span,strong,em,code,abbr,time, etc.
Type Safety
StructFlow provides comprehensive type hints:
from typing import Optional
from structflow.tags import div, span, meta, link
# Type-safe element creation
container: div = div(
span("Hello", class_="greeting"),
id_="main-container"
)
# Head elements with proper typing
metadata: meta = meta(
name="viewport",
content="width=device-width, initial-scale=1"
)
# Attributes are properly typed
stylesheet: link = link(
rel="stylesheet", # Literal type
href="styles.css", # str
media="screen" # str
)
Best Practices
- Organize head elements logically: Group related metadata together
- Use semantic HTML: Choose elements based on meaning, not appearance
- Leverage type hints: Let your IDE help you with autocompletion
- Structure your code: Break complex layouts into functions
- Separate concerns: Keep head metadata separate from body content
def create_page_head(title: str, description: str) -> tuple:
"""Create standard head elements for a page."""
return (
title(title),
meta(charset="utf-8"),
meta(name="viewport", content="width=device-width, initial-scale=1"),
meta(name="description", content=description),
link(rel="stylesheet", href="styles.css")
)
def create_card(title: str, content: str, image_url: str) -> div:
"""Create a reusable card component."""
return div(
img(src=image_url, alt=title, class_="card-image"),
div(
h3(title, class_="card-title"),
p(content, class_="card-content"),
class_="card-body"
),
class_="card"
)
# Usage
doc = Document(
*create_page_head("My Site", "Welcome to my website"),
html_lang="en"
)
doc.add(
create_card(
title="Product Name",
content="Product description here...",
image_url="product.jpg"
)
)
License
This project is licensed under the MIT License.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Support
If you encounter any problems or have questions, please open an issue on GitHub.
Release files for structflow 3.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| structflow-3.0.1.tar.gz | 17.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| structflow-3.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 41.5 kB
Release files / structflow-3.0.1.tar.gz
| Download URL | structflow-3.0.1.tar.gz |
|---|---|
| Size | 17.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
44cb5a5e9d808e4d31fac8c04ae8ee6a776f9c25573a93b5d471d08d00056673
|
|
BLAKE2b-256 checksum How to use checksums |
d007ac973193c76e657e02816971709ce321dd0cefabf8051b834b050c12e948
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.3
|
Release files / structflow-3.0.1-py3-none-any.whl
| Download URL | structflow-3.0.1-py3-none-any.whl |
|---|---|
| Size | 24.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6bd272f5dfd6c8496b84956c530c00799cf2ea86f3e3def05d5026d34bc18274
|
|
BLAKE2b-256 checksum How to use checksums |
65411f55dad92bd55e3e984a18e2e6ef0670fe17b40f7859c79576dd5091987a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.3
|