Convert data structures to HTML for any Python web framework
Project description
PyStructUI 🎨
Transform data structures into beautiful UIs for any Python web framework
PyStructUI is a universal presentation layer that lets you build web UIs using pure data structures instead of HTML templates. Works with Flask, Django, FastAPI, and any Python web framework.
Why PyStructUI?
Traditional web development:
<!-- 100s of HTML template files -->
<div class="card">
<div class="card-header">{{ title }}</div>
<div class="card-body">{{ content }}</div>
</div>
With PyStructUI:
{'type': 'card', 'title': 'Hello', 'body': 'World'}
Benefits:
- ✅ No HTML templates - Define UI as data
- ✅ Framework agnostic - Works with Flask, Django, FastAPI, etc.
- ✅ UI framework swappable - Switch between Bootstrap, Tailwind, Material with one line
- ✅ 90% less code - Data structures are more concise than HTML
- ✅ AI-friendly - LLMs understand data better than HTML
- ✅ Testable - Test data structures, not HTML strings
Installation
pip install pystructui
Or install with framework support:
pip install pystructui[flask]
pip install pystructui[django]
pip install pystructui[fastapi]
Quick Start
Basic Usage
from pystructui import render
# Define UI as data
ui_data = {
'type': 'page',
'title': 'My App',
'components': [
{'type': 'navbar', 'brand': 'PyStructUI'},
{'type': 'hero', 'title': 'Welcome!', 'subtitle': 'Build UIs with data'},
{'type': 'button', 'text': 'Get Started', 'variant': 'primary'}
]
}
# Render to HTML
html = render(ui_data)
Flask Integration
from flask import Flask
from pystructui import flask_integration
app = Flask(__name__)
ui = flask_integration(app)
@app.route('/')
@ui.render
def index():
return {
'type': 'page',
'title': 'Flask App',
'components': [
{'type': 'card', 'title': 'Hello Flask!', 'body': 'No templates needed!'}
]
}
Django Integration
# views.py
from pystructui import django_integration
ui = django_integration()
def index(request):
data = {
'type': 'page',
'title': 'Django App',
'components': [
{'type': 'navbar', 'brand': 'Django + PyStructUI'},
{'type': 'hero', 'title': 'No templates!'}
]
}
return ui.render_response(data)
FastAPI Integration
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from pystructui import fastapi_integration
app = FastAPI()
ui = fastapi_integration()
@app.get("/", response_class=HTMLResponse)
async def index():
data = {
'type': 'page',
'components': [{'type': 'card', 'title': 'FastAPI + PyStructUI'}]
}
return ui.render(data)
Component Reference
Page Structure
{
'type': 'page',
'title': 'Page Title',
'components': [...] # List of components
}
Navigation
{
'type': 'navbar',
'brand': 'My App',
'links': [
{'text': 'Home', 'url': '/'},
{'text': 'About', 'url': '/about'}
]
}
Cards
{
'type': 'card',
'title': 'Card Title',
'body': 'Card content or nested component',
'footer': {'type': 'button', 'text': 'Action'}
}
Forms
{
'type': 'form',
'method': 'POST',
'action': '/submit',
'fields': [
{
'type': 'text',
'name': 'username',
'label': 'Username',
'required': True
},
{
'type': 'textarea',
'name': 'message',
'label': 'Message'
}
]
}
Tables
{
'type': 'table',
'headers': ['Name', 'Email', 'Status'],
'rows': [
['John', 'john@example.com', 'Active'],
['Jane', 'jane@example.com', 'Pending']
]
}
Grids
{
'type': 'grid',
'columns': 3,
'items': [
{'type': 'card', 'title': 'Card 1'},
{'type': 'card', 'title': 'Card 2'},
{'type': 'card', 'title': 'Card 3'}
]
}
Alerts
{
'type': 'alert',
'message': 'Operation successful!',
'variant': 'success', # success, danger, warning, info
'dismissible': True
}
Switching UI Frameworks
from pystructui import PresentationLayer
from pystructui.renderers import BootstrapRenderer, TailwindRenderer
pl = PresentationLayer()
# Use Bootstrap
pl.add_renderer('bootstrap', BootstrapRenderer())
html = pl.render(data, 'bootstrap')
# Switch to Tailwind - same data, different output!
pl.add_renderer('tailwind', TailwindRenderer())
html = pl.render(data, 'tailwind')
Custom Renderers
Create your own renderer for any UI framework:
from pystructui import Renderer
class CustomRenderer(Renderer):
def render(self, data):
# Your rendering logic
return html
def render_component(self, component):
# Component rendering
return html
# Use it
pl.add_renderer('custom', CustomRenderer())
Advanced Features
Nested Components
Components can be nested infinitely:
{
'type': 'card',
'body': {
'type': 'grid',
'columns': 2,
'items': [
{'type': 'button', 'text': 'Yes'},
{'type': 'button', 'text': 'No'}
]
}
}
Raw HTML
When needed, include raw HTML:
{
'type': 'raw',
'content': '<custom-element>Custom HTML</custom-element>'
}
Dynamic Rendering
Use Python to generate dynamic UIs:
def dashboard(user_data):
return {
'type': 'grid',
'columns': 3,
'items': [
{
'type': 'card',
'title': metric['name'],
'body': metric['value']
}
for metric in user_data.metrics
]
}
Why Data Structures?
- Simplicity - No template syntax to learn
- Portability - Same structure works with any renderer
- Testability - Assert on data, not HTML strings
- AI-friendly - LLMs excel at data transformation
- Version control - Data diffs are cleaner than HTML diffs
- Performance - No template compilation overhead
Comparison
Traditional Django Template
{% extends "base.html" %}
{% block content %}
<div class="container">
<div class="row">
{% for item in items %}
<div class="col-md-4">
<div class="card">
<div class="card-body">
<h5 class="card-title">{{ item.title }}</h5>
<p class="card-text">{{ item.description }}</p>
<a href="{{ item.url }}" class="btn btn-primary">View</a>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
With PyStructUI
{
'type': 'grid',
'columns': 3,
'items': [
{
'type': 'card',
'title': item['title'],
'body': item['description'],
'footer': {'type': 'button', 'text': 'View', 'url': item['url']}
}
for item in items
]
}
Real-World Example
Building a complete todo app:
from flask import Flask
from pystructui import flask_integration
app = Flask(__name__)
ui = flask_integration(app)
todos = []
@app.route('/')
@ui.render
def index():
return {
'type': 'page',
'components': [
{'type': 'navbar', 'brand': 'Todo App'},
{
'type': 'card',
'title': 'My Todos',
'body': {
'type': 'table',
'headers': ['Task', 'Status'],
'rows': [[t['text'], t['status']] for t in todos]
}
}
]
}
# That's it! No templates needed!
Contributing
We welcome contributions! PyStructUI is designed to be extensible:
- Add new component types
- Create renderers for more UI frameworks
- Add framework integrations
- Improve documentation
License
MIT License - Use PyStructUI in any project!
Philosophy
"Code is about data structures. UI should be too."
PyStructUI embraces the fundamental truth that all programming is data transformation. Instead of mixing logic with presentation through templates, we keep them separate: logic produces data, renderers transform data to UI.
This is the future of web development - where humans define intent through data structures, and machines handle the implementation details.
Support
- GitHub: github.com/askrobots/PyStructUI
- Documentation: pystructui.readthedocs.io
- PyPI: pypi.org/project/pystructui
Built with ❤️ by the DBBasic team. Part of the movement to make web development simpler, faster, and more enjoyable.
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 pystructui-0.1.0.tar.gz.
File metadata
- Download URL: pystructui-0.1.0.tar.gz
- Upload date:
- Size: 15.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65b770a9a57c1d7d1f6938df4fcc1ed5acf0b152eda0fe726f447c054b948ae6
|
|
| MD5 |
d183beef59a50e6309e43abf77a0c52d
|
|
| BLAKE2b-256 |
a188b7aa3341847a97dc5391d3e8a9148a5a6fd0ca805045d9cf05cb696ea69d
|
File details
Details for the file pystructui-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pystructui-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
849fc5f21f14ac2834ea5b752f08fc55f8add62cd407cf87a364941300d9d1da
|
|
| MD5 |
0f16c19fb72e56f539285f59c82eab7c
|
|
| BLAKE2b-256 |
96e1351c8c4ace9363c26254a1012d08e8078b2ff66eb19d4c5df98b15da3a5c
|