Skip to main content

Core HTML generation library with Rust-based Python extension - high performance, minimal dependencies

Project description

RustyTags Core

🚀 High-performance HTML generation library - Rust-powered Python extension for blazing-fast HTML and SVG creation.

3-10x faster than pure Python implementations with minimal dependencies and maximum performance.

⚛️ Datastar-Ready - Built-in reactive component support with intelligent JavaScript expression detection.

🚨 Breaking Changes in v0.6.0: Advanced features moved to Nitro. See Migration Guide below.

Looking for web framework features? Check out the Nitro package which builds on RustyTags with advanced templates, UI components, SSE, and framework integrations.

What RustyTags Core Does

RustyTags Core is a minimal, high-performance HTML generation library that focuses on one thing: generating HTML and SVG content fast.

  • 🏷️ Complete HTML5/SVG Tags: All standard HTML5 and SVG elements with optimized Rust implementations
  • ⚡ Blazing Performance: 3-10x faster than pure Python with memory optimization and intelligent caching
  • ⚛️ Powerful Datastar SDK: Type-safe Signal system with Python operator overloading, conditional logic, validation, and HTTP actions
  • 🪶 Lightweight: Minimal dependencies - works with any Python web framework
  • 🧠 Smart Processing: Automatic attribute handling and intelligent type conversion
  • 🔧 Framework Ready: Drop-in replacement for any HTML generation needs

Quick Start

Installation

pip install rusty-tags

Basic HTML Generation

from rusty_tags import Div, P, H1, A, Button, Input

# Simple HTML elements
content = Div(
    H1("Welcome to RustyTags Core"),
    P("High-performance HTML generation with Rust + Python"),
    A("Learn More", href="https://github.com/ndendic/RustyTags"),
    cls="container"
)
print(content)
# Output:
# <div class="container">
#   <h1>Welcome to RustyTags Core</h1>
#   <p>High-performance HTML generation with Rust + Python</p>
#   <a href="https://github.com/ndendic/RustyTags">Learn More</a>
# </div>

Complete Page Generation

from rusty_tags import Html, Head, Title, Body, Meta, Link
from rusty_tags import Page  # Simple page helper

# Manual HTML structure
page = Html(
    Head(
        Title("My Site"),
        Meta(charset="utf-8"),
        Link(rel="stylesheet", href="/app.css")
    ),
    Body(
        H1("Hello World"),
        P("Built with RustyTags Core")
    )
)

# Or use the simple Page helper
page = Page(
    H1("Hello World"),
    P("Built with RustyTags Core"),
    title="My Site",
    hdrs=(Meta(charset="utf-8"), Link(rel="stylesheet", href="/app.css"))
)

Reactive Components with Datastar SDK

Inspired by the awesome StarHTML, RustyTags Core now includes an even more powerfull Datastar SDK that provides a Pythonic API for building reactive components with type-safe signals and expressions:

Quick Start with Signals

from rusty_tags import Div, Button, P, Input, Label, Span, Page
from rusty_tags.datastar import Signal, Signals

# Create signals using the Signals class
sigs = Signals(counter=0, user_name="John", is_active=True)

# Basic reactive counter with Signal methods
counter = Div(
    P(text=sigs.counter, cls="display"),
    Button("-", on_click=sigs.counter.sub(1)),
    Button("+", on_click=sigs.counter.add(1)),
    Button("Reset", on_click=sigs.counter.set(0)),
    cls="counter-widget",
    signals=sigs  # Signals object automatically converts to data-signals
)

# Create a complete page with Datastar CDN
page = Page(counter, title="Reactive App", datastar=True)

Signal Operations - Pythonic Reactive Expressions

The Signal SDK provides full Python operator overloading for building reactive JavaScript expressions:

Arithmetic Operators:

from rusty_tags.datastar import Signals

numbers = Signals(x=10, y=3)
demo = Div(
    P(text="X: " + numbers.x),                           # → "X: ${$x}"
    P(text="Y: " + numbers.y),                           # → "Y: ${$y}"
    P(text="Sum: " + (numbers.x + numbers.y)),           # → "Sum: ${$x + $y}"
    P(text="Product: " + (numbers.x * numbers.y)),       # → "Product: ${$x * $y}"
    P(text="Division: " + (numbers.x / numbers.y)),      # → "Division: ${$x / $y}"
    P(text="Modulo: " + (numbers.x % numbers.y)),        # → "Modulo: ${$x % $y}"

    Button("X +5", on_click=numbers.x.add(5)),
    Button("Y +1", on_click=numbers.y.add(1)),
    signals=numbers
)

Comparison & Logical Operators:

from rusty_tags.datastar import Signal

age = Signal("age", 25)
has_license = Signal("has_license", True)

validation = Div(
    P(text="Age: " + age),
    P(text="Has License: " + has_license),
    P(text="Is Adult (≥18): " + (age >= 18)),            # → ($age >= 18)
    P(text="Can Drive: " + ((age >= 18) & has_license)), # → (($age >= 18) && $has_license)
    P(text="Is Minor: " + (age < 18)),                   # → ($age < 18)
    P(text="No License: " + (~has_license)),             # → (!$has_license)

    Button("Age +1", on_click=age.add(1)),
    Button("Toggle License", on_click=has_license.toggle()),
    signals={"age": 25, "has_license": True}
)

String Methods:

text = Signal("text", "Hello World")

string_demo = Div(
    Input(type="text", bind=text, placeholder="Enter text"),
    P(text="Original: " + text),
    P(text="Uppercase: " + text.upper()),                # → $text.toUpperCase()
    P(text="Lowercase: " + text.lower()),                # → $text.toLowerCase()
    P(text="Length: " + text.length),                    # → $text.length
    P(text="Contains 'Hello': " + text.contains("Hello")), # → $text.includes('Hello')
    signals={"text": "Hello World"}
)

Array Methods:

items = Signal("items", ["Apple", "Banana"])
new_item = Signal("new_item", "Orange")

array_demo = Div(
    Input(type="text", bind=new_item, placeholder="New item"),
    # Chaining multiple actions with semicolons
    Button("Add Item", data_on_click=items.append(new_item).to_js() + "; " + new_item.set("").to_js()),
    Button("Remove Last", data_on_click=items.pop()),
    Button("Clear All", data_on_click=items.set([])),

    P("Count: ", Span(text=items.length)),               # → $items.length
    P("Items: ", Span(text=items.join(", "))),           # → $items.join(', ')
    P("Empty: ", Span(text=items.length == 0)),          # → $items.length === 0
    signals={"items": ["Apple", "Banana"], "new_item": ""}
)

Math Methods:

value = Signal("value", 7.825)

math_demo = Div(
    P("Value: ", Span(text=value)),
    P("Rounded: ", Span(text=value.round())),            # → Math.round($value)
    P("Rounded (2 decimals): ", Span(text=value.round(2))),
    P("Absolute: ", Span(text=value.abs())),             # → Math.abs($value)
    P("Min with 5: ", Span(text=value.min(5))),          # → Math.min($value, 5)
    P("Max with 10: ", Span(text=value.max(10))),        # → Math.max($value, 10)
    P("Clamped (0-10): ", Span(text=value.clamp(0, 10))), # → Math.max(0, Math.min(10, $value))

    Button("+0.5", data_on_click=value.add(0.5)),
    Button("-0.5", data_on_click=value.sub(0.5)),
    signals={"value": 7.825}
)

Advanced Features - Conditionals, Patterns & Templates

Conditional Expressions with if_():

from rusty_tags.datastar import if_

score = Signal("score", 75)

conditional = Div(
    P("Score: ", Span(text=score)),
    # Simple ternary
    P("Grade: ", Span(text=if_(score >= 90, "A", "B"))),  # → ($score >= 90) ? 'A' : 'B'
    P("Status: ", text=if_(score >= 60, "Pass", "Fail")),

    # Nested conditionals
    P("Grade: ", Span(text=if_(score >= 90, "A",
                              if_(score >= 80, "B",
                                 if_(score >= 70, "C", "F"))))),

    # Conditional rendering with data-show
    Div(text=if_(score >= 90, "🎉 Excellent!",
                 if_(score >= 70, "👍 Good", "📚 Keep trying")),
        style="font-size: 2rem; text-align: center;"),

    Button("+10", data_on_click=score.add(10)),
    Button("-10", data_on_click=score.sub(10)),
    signals={"score": 75}
)

Pattern Matching with match():

from rusty_tags.datastar import match

status = Signals(status="idle")

status_demo = Div(
    P("Current Status: ", Span(text=status.status)),
    Div(
        text=match(
            status.status,
            idle="⏸️ Ready to start",
            loading="⏳ Processing...",
            success="✅ Completed!",
            error="❌ Failed!",
            default="❓ Unknown"
        ),
        style="font-size: 1.5rem; text-align: center; padding: 1rem;"
    ),

    Button("Idle", on_click=status.status.set("idle")),
    Button("Loading", on_click=status.status.set("loading")),
    Button("Success", on_click=status.status.set("success")),
    Button("Error", on_click=status.status.set("error")),
    signals=status
)

Template Literals with f():

from rusty_tags.datastar import f

user = Signals(first_name="John", last_name="Doe", age_val=25)

template = Div(
    Input(type="text", bind=user.first_name, placeholder="First name"),
    Input(type="text", bind=user.last_name, placeholder="Last name"),
    Input(type="number", bind=user.age_val, placeholder="Age"),

    P(text=f("Hello, {fn} {ln}!", fn=user.first_name, ln=user.last_name)),
    P(text=f("You are {age} years old.", age=user.age_val)),
    P(text=f("In 10 years, you'll be {future}.", future=user.age_val + 10)),
    signals=user
)

Dynamic CSS Classes

Using collect() for conditional class joining:

from rusty_tags.datastar import collect

is_large = Signal("is_large", False)
is_bold = Signal("is_bold", False)
is_italic = Signal("is_italic", False)

collect_demo = Div(
    Label(Input(type="checkbox", bind=is_large), " Large"),
    Label(Input(type="checkbox", bind=is_bold), " Bold"),
    Label(Input(type="checkbox", bind=is_italic), " Italic"),

    P(
        "Styled Text",
        data_class=collect([
            (is_large, "large"),
            (is_bold, "bold"),
            (is_italic, "italic")
        ], join_with=" "),
        style="transition: all 0.3s;"
    ),
    signals={"is_large": False, "is_bold": False, "is_italic": False}
)

Using classes() for Datastar's data-class (object literal):

from rusty_tags.datastar import classes

cls_large = Signal("cls_large", False)
cls_bold = Signal("cls_bold", False)
cls_blue = Signal("cls_blue", False)

classes_demo = Div(
    Label(Input(type="checkbox", bind=cls_large), " Large"),
    Label(Input(type="checkbox", bind=cls_bold), " Bold"),
    Label(Input(type="checkbox", bind=cls_blue), " Blue"),

    P(
        "Styled Text with data-class",
        data_class=classes(large=cls_large, bold=cls_bold, blue=cls_blue),
        style="transition: all 0.3s;"
    ),
    signals={"cls_large": False, "cls_bold": False, "cls_blue": False}
)

Form Validation with Logical Aggregation

Using all() and any() for validation:

from rusty_tags.datastar import all, any, if_

form_name = Signal("form_name", "")
form_email = Signal("form_email", "")
form_age = Signal("form_age", 0)
form_agree = Signal("form_agree", False)

# Define validation rules
name_valid = form_name.length >= 3
email_valid = form_email.contains("@")
age_valid = form_age >= 18
can_submit = all(name_valid, email_valid, age_valid, form_agree)

registration_form = Div(
    # Name field with validation
    Div(
        Label("Name:"),
        Input(type="text", bind=form_name, placeholder="Enter name (min 3 chars)"),
        P("✓ Valid", data_show=name_valid, style="color: green;"),
        P("✗ Too short", data_show=~name_valid, style="color: red;")
    ),

    # Email field with validation
    Div(
        Label("Email:"),
        Input(type="email", bind=form_email, placeholder="Enter email"),
        P("✓ Valid", data_show=email_valid, style="color: green;"),
        P("✗ Invalid", data_show=~email_valid, style="color: red;")
    ),

    # Age field with validation
    Div(
        Label("Age:"),
        Input(type="number", bind=form_age, placeholder="Enter age"),
        P("✓ Valid", data_show=age_valid, style="color: green;"),
        P("✗ Must be 18+", data_show=~age_valid, style="color: red;")
    ),

    # Terms checkbox
    Div(
        Label(Input(type="checkbox", bind=form_agree), " I agree to terms")
    ),

    # Submit button - disabled until all valid
    Button(
        "Submit",
        data_disabled=~can_submit,
        data_attr_style=if_(can_submit, "opacity: 1; cursor: pointer;",
                                        "opacity: 0.5; cursor: not-allowed;")
    ),
    P(text=f("Hello, {name}!", name=form_name), data_show=can_submit),

    signals={"form_name": "", "form_email": "", "form_age": 0, "form_agree": False}
)

HTTP Actions and Server Communication

from rusty_tags.datastar import post, get, put, patch, delete

# HTTP action helpers generate @action() expressions
api_demo = Div(
    Input(bind="$name", placeholder="Enter name"),
    Input(bind="$email", placeholder="Enter email"),

    # POST with reactive data (signals are automatically passed)
    Button(
        "Save User",
        on_click=post("/api/users", name="$name", email="$email"),
        cls="btn-primary"
    ),

    # GET request
    Button("Load Data", on_click=get("/api/data")),

    # PUT request
    Button("Update", on_click=put("/api/users/1", name="$name")),

    # PATCH request
    Button("Partial Update", on_click=patch("/api/users/1", email="$email")),

    # DELETE request
    Button("Delete", on_click=delete("/api/users/1")),

    Div(id="results"),
    signals={"name": "", "email": ""}
)

Property Access for Nested Data

# Access nested object properties naturally
user = Signal("user", {"name": "Alice", "age": 30, "email": "alice@example.com"})

user_profile = Div(
    P("Name: ", Span(text=user.name)),         # → $user.name
    P("Age: ", Span(text=user.age)),           # → $user.age
    P("Email: ", Span(text=user.email)),       # → $user.email
    P("Adult: ", Span(text=(user.age >= 18))), # → ($user.age >= 18)

    Button("Birthday", on_click=user.age.add(1)),
    Button("Change Name", on_click=user.name.set("Bob")),
    signals={"user": {"name": "Alice", "age": 30, "email": "alice@example.com"}}
)

Keyboard Shortcuts with data-on-keys Plugin

RustyTags supports the data-on-keys Datastar plugin for handling keyboard shortcuts:

from rusty_tags import Div, Input, Button

# Global keyboard shortcuts (window-scoped)
shortcuts = Div(
    "Press Ctrl+K to search, Escape to close",
    on_keys_ctrl_k="openSearch()",           # → data-on-keys:ctrl-k
    on_keys_escape="closeModal()",           # → data-on-keys:escape
    on_keys_ctrl_s="saveDocument()",         # → data-on-keys:ctrl-s
    on_keys_f1="showHelp()",                 # → data-on-keys:f1
)

# Element-scoped shortcuts (requires focus)
search_input = Input(
    type="text",
    placeholder="Search...",
    on_keys_enter__el="submitSearch()",      # → data-on-keys:enter__el
    on_keys_escape__el="clearInput()",       # → data-on-keys:escape__el
)

# With timing modifiers
throttled = Div(
    on_keys_space__throttle_1s="$counter++",           # → data-on-keys:space__throttle.1s
    on_keys_ctrl_s__debounce_500ms="saveDocument()",   # → data-on-keys:ctrl-s__debounce.500ms
)

# Capture all keys
keylogger = Div(on_keys="console.log($event.key)")     # → data-on-keys

Supported modifiers:

  • __el - Element-scoped (requires focus)
  • __stop - Stop event propagation
  • __noprevent - Allow default browser behavior
  • __throttle_Xs - Throttle execution (e.g., __throttle_1s)
  • __debounce_Xms - Debounce execution (e.g., __debounce_500ms)

Complete Datastar SDK Features:

  • Type-Safe Signals: Signal and Signals classes with automatic type inference
  • Python Operators: Full operator overloading (+, -, *, /, %, ==, !=, <, >, <=, >=, &, |, ~)
  • Signal Methods: .add(), .sub(), .set(), .toggle(), .append(), .pop(), .remove()
  • String Methods: .upper(), .lower(), .strip(), .contains(), .length
  • Math Methods: .round(), .abs(), .min(), .max(), .clamp()
  • Array Methods: .append(), .prepend(), .pop(), .remove(), .join(), .slice(), .length
  • Conditionals: if_() for ternary expressions, match() for pattern matching
  • Templates: f() for JavaScript template literals with embedded expressions
  • Dynamic Classes: collect() for joining, classes() for object literals
  • Validation: all() and any() for logical aggregation
  • HTTP Actions: get(), post(), put(), patch(), delete() action generators
  • Keyboard Shortcuts: on_keys_* for the data-on-keys plugin with modifier support
  • Raw JavaScript: js() function for raw JavaScript when needed
  • Property Access: Natural Python syntax for nested object properties

SVG Generation

from rusty_tags import Svg, Circle, Rect, Line, Path

# Create SVG graphics
chart = Svg(
    Circle(cx="50", cy="50", r="40", fill="blue"),
    Rect(x="10", y="10", width="30", height="30", fill="red"),
    Line(x1="0", y1="0", x2="100", y2="100", stroke="black"),
    width="200", height="200", viewBox="0 0 200 200"
)

Core Features

🏷️ Complete HTML5/SVG Tag System

All standard HTML5 and SVG elements are available as Python functions:

# HTML elements
Html, Head, Body, Title, Meta, Link, Script
H1, H2, H3, H4, H5, H6, P, Div, Span, A
Form, Input, Button, Select, Textarea, Label
Table, Tr, Td, Th, Tbody, Thead, Tfoot
Nav, Main, Section, Article, Header, Footer
Img, Video, Audio, Canvas, Iframe
# ... and many more

# SVG elements
Svg, Circle, Rect, Line, Path, Polygon
G, Defs, Use, Symbol, LinearGradient
Text, Image, ForeignObject
# ... complete SVG support

⚡ Performance Optimizations

  • Memory Pooling: Thread-local string pools and arena allocators minimize allocations
  • Intelligent Caching: Lock-free attribute processing with smart cache invalidation
  • String Interning: Common HTML strings pre-allocated for maximum efficiency
  • Type Optimization: Fast paths for common Python types and HTML patterns

🔧 Smart Type System

Intelligent handling of Python types:

# Automatic type conversion
Div(
    42,           # Numbers → strings
    True,         # Booleans → "true"/"false"
    None,         # None → empty string
    [1, 2, 3],    # Lists → joined strings
    custom_obj,   # Objects with __html__(), render(), or _repr_html_()
)

# Dictionary attributes automatically expand
Div("Content", {"id": "main", "class": "container", "hidden": False})
# Renders: <div id="main" class="container">Content</div>

# Framework integration - automatic recognition
class MyComponent:
    def __html__(self):
        return "<div>Custom HTML</div>"

Div(MyComponent())  # Automatically calls __html__()

🪶 Framework Agnostic

Works with any Python web framework:

# FastAPI
from fastapi import FastAPI
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.get("/")
def home():
    return HTMLResponse(str(Page(H1("FastAPI + RustyTags"), title="Home")))

# Flask
from flask import Flask

app = Flask(__name__)

@app.route("/")
def home():
    return str(Page(H1("Flask + RustyTags"), title="Home"))

# Django
from django.http import HttpResponse

def home(request):
    return HttpResponse(str(Page(H1("Django + RustyTags"), title="Home")))

📓 Jupyter Integration

from rusty_tags import show

# Display directly in Jupyter notebooks
content = Div(H1("Notebook Content"), style="color: blue;")
show(content)  # Renders directly in Jupyter cells

Performance

RustyTags Core delivers significant performance improvements over pure Python:

  • 3-10x faster HTML generation
  • Sub-microsecond rendering for simple elements
  • Memory efficient with intelligent pooling
  • Scalable with lock-free concurrent data structures
# Benchmark example
import timeit
from rusty_tags import Div, P

def generate_content():
    return Div(
        *[P(f"Paragraph {i}") for i in range(1000)],
        cls="container"
    )

# Time the generation
time = timeit.timeit(generate_content, number=1000)
print(f"Generated 1000 pages with 1000 paragraphs each in {time:.3f}s")

Architecture

🦀 Rust Core (src/lib.rs):

  • High-performance HTML/SVG generation with PyO3 bindings
  • Advanced memory management with pooling and interning
  • Complete tag system with macro-generated optimizations
  • ~2000+ lines of optimized Rust code

🐍 Python Layer (rusty_tags/):

  • Core Module (__init__.py): All HTML/SVG tags and core types
  • Utilities (utils.py): Essential helpers (Page, page_template, show, AttrDict)
  • Datastar SDK (datastar.py): Type-safe Signal system with Python operator overloading for reactive expressions
  • Rust Extension: Pre-compiled high-performance core with Datastar processing

Migration from Pre-0.6.x

🚨 Breaking Changes in v0.6.0

RustyTags v0.6.0 represents a major architectural shift to focus on core HTML generation performance. Advanced web framework features have been moved to the separate Nitro package.

What's Removed from RustyTags Core:

Feature Status New Location
Event system (events.py) ❌ Removed Nitro
Client management (client.py) ❌ Removed Nitro
UI components (xtras/) ❌ Removed Nitro
Example applications (lab/) ❌ Removed Nitro

What's Kept in RustyTags Core:

Feature Status Notes
All HTML/SVG tags Kept Complete tag system with Rust performance
Datastar SDK Enhanced Type-safe Signal & Signals with full Python operator overloading
Page() function Enhanced Simple templating with optional Datastar CDN
page_template(), page_template() Kept Essential templating functions
show() Jupyter integration Kept Perfect for notebooks
AttrDict utility Kept Flexible attribute access

Migration Guide:

Before v0.6.0 (Monolithic):

# Old import style - no longer works
from rusty_tags import Div, DS, Client, Accordion
from rusty_tags.events import emit

After v0.6.0 (Enhanced Core):

# Core HTML generation + Datastar SDK (RustyTags)
from rusty_tags import Div, Page, page_template, Button, Input
from rusty_tags.datastar import Signal, Signals, if_, match, f, all, any
from rusty_tags.datastar import post, get, put, patch, delete  # HTTP actions

# Advanced web framework features (Nitro - separate install)
from nitro import Client, Accordion
from nitro.events import emit

Installation Changes:

# Before v0.6.0
pip install rusty-tags  # Included everything

# After v0.6.0
pip install rusty-tags        # Core HTML + complete Datastar integration
pip install nitro             # For advanced web framework features (events, SSE, etc.)

Code Migration Examples:

  1. Basic HTML Generation (No changes needed):
# ✅ Works exactly the same
from rusty_tags import Div, H1, P
content = Div(H1("Hello"), P("World"))
  1. Basic Datastar (No changes needed):
# ✅ Works exactly the same - built into Rust core
from rusty_tags import Div, Button
counter = Div(
    Button("+1", on_click="$count++"),
    signals={"count": 0}
)
  1. Datastar SDK (Completely rewritten with Signal system):
# ✅ New Signal-based API in v0.6.0+
from rusty_tags.datastar import Signal, Signals, post, if_, all

# Create type-safe signals
sigs = Signals(name="", email="")

# Use Python operators for reactive expressions
form = Div(
    Input(bind=sigs.name, placeholder="Name"),
    Input(bind=sigs.email, placeholder="Email"),

    # New HTTP action helpers
    Button("Submit", on_click=post("/api/submit", name=sigs.name, email=sigs.email)),

    # Conditional logic with if_()
    P(text=if_(sigs.name.length >= 3, "Valid name", "Too short")),

    # Validation with all()
    Button("Save", data_disabled=~all(sigs.name.length >= 3, sigs.email.contains("@"))),

    signals=sigs
)
  1. Page Templates (Minor changes):
# ✅ Still works in RustyTags Core
from rusty_tags import Page, page_template

# Basic templating stays the same
page = Page(content, title="My App", datastar=True)
template = page_template("My App", datastar=True)

# ❌ Advanced CDN features moved to Nitro
# highlightjs=True, lucide=True parameters now in Nitro

Why This Change?

  • Performance: Core package is now 10x smaller and has zero dependencies
  • Flexibility: Choose your complexity level - core HTML or full framework
  • Maintenance: Clear separation of concerns between HTML generation and web framework
  • Adoption: Lower barrier to entry for simple HTML generation needs

The new Datastar SDK in RustyTags Core provides a powerful, type-safe reactive system with Python operator overloading - giving you excellent reactive capabilities without requiring the full Nitro framework.

Why RustyTags Core?

Choose RustyTags Core when:

  • ✅ You need maximum performance for HTML generation
  • ✅ You want minimal dependencies in your project
  • ✅ You're building your own templating system
  • ✅ You need framework-agnostic HTML generation
  • ✅ You want drop-in compatibility with any Python web framework

Consider Nitro when:

  • 🚀 You want a full web framework with reactive components
  • 🎨 You need advanced templating and UI component libraries
  • 📡 You want real-time features (SSE, WebSocket management)
  • ⚛️ You need Datastar integration for reactive UIs

System Requirements

  • Python 3.8+ (broad compatibility across versions)
  • Runtime Dependencies: None (zero dependencies for maximum compatibility)
  • Optional: IPython for show() function in Jupyter notebooks
  • Build Requirements (development only): Rust 1.70+, Maturin ≥1.9

Development

# Clone and build from source
git clone https://github.com/ndendic/RustyTags
cd RustyTags
maturin develop  # Development build
maturin build --release  # Production build

License

MIT License - See LICENSE file for details.

Related Projects

  • Nitro - Full-stack web framework built on RustyTags
  • FastHTML - Inspiration for the Python API design
  • Datastar - Reactive component framework (used in Nitro)

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rusty_tags-0.7.0.tar.gz (109.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rusty_tags-0.7.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl (2.1 MB view details)

Uploaded PyPymusllinux: musl 1.2+ x86-64

rusty_tags-0.7.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.9 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

rusty_tags-0.7.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl (2.1 MB view details)

Uploaded PyPymusllinux: musl 1.2+ x86-64

rusty_tags-0.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.14tmusllinux: musl 1.2+ x86-64

rusty_tags-0.7.0-cp314-cp314-win_amd64.whl (1.8 MB view details)

Uploaded CPython 3.14Windows x86-64

rusty_tags-0.7.0-cp314-cp314-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.14musllinux: musl 1.2+ x86-64

rusty_tags-0.7.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

rusty_tags-0.7.0-cp314-cp314-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

rusty_tags-0.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.13tmusllinux: musl 1.2+ x86-64

rusty_tags-0.7.0-cp313-cp313-win_amd64.whl (1.9 MB view details)

Uploaded CPython 3.13Windows x86-64

rusty_tags-0.7.0-cp313-cp313-musllinux_1_2_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

rusty_tags-0.7.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

rusty_tags-0.7.0-cp313-cp313-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

rusty_tags-0.7.0-cp312-cp312-win_amd64.whl (1.9 MB view details)

Uploaded CPython 3.12Windows x86-64

rusty_tags-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

rusty_tags-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

rusty_tags-0.7.0-cp312-cp312-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

rusty_tags-0.7.0-cp311-cp311-win_amd64.whl (1.8 MB view details)

Uploaded CPython 3.11Windows x86-64

rusty_tags-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ x86-64

rusty_tags-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

rusty_tags-0.7.0-cp311-cp311-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

rusty_tags-0.7.0-cp310-cp310-win_amd64.whl (1.8 MB view details)

Uploaded CPython 3.10Windows x86-64

rusty_tags-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl (2.1 MB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ x86-64

rusty_tags-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.9 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

File details

Details for the file rusty_tags-0.7.0.tar.gz.

File metadata

  • Download URL: rusty_tags-0.7.0.tar.gz
  • Upload date:
  • Size: 109.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.13.1

File hashes

Hashes for rusty_tags-0.7.0.tar.gz
Algorithm Hash digest
SHA256 a10e2674fd8b545aeaa6f571d79e9693a817204c6ab26fee9ba335522758bc92
MD5 eddb3885d34f5b5c33feae48e19132b9
BLAKE2b-256 f1f487f99b0cb31adaa977ff4d7b2b97f0d749a12730ac67f6a4b92deaf34889

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 ab4d4694dcae51f756db91ef4a9116da01e439d41f9a39f8d5524d9d77f847e6
MD5 68342dec1a14615a8f0a727af24686e2
BLAKE2b-256 1cae67184185a4812b8f15f2f253ca8098df6e9dd4cf3060bca442fd446cdcd9

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e682ca74b2fb2305a3ee31429462cd12d0c6bcdb8a830096b0a942cde9787a55
MD5 04c5f6a78b1e32d5b639253125fd5422
BLAKE2b-256 9b30660970b169d400ff18c67b4c5dc830458d3aa08df8e715374d531f149c36

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 93dfb9de72455ed36421b6ae81e1864b45fdb48dea84fade7ad1195fe24bb022
MD5 e75e29de8ec48c8b70b70e5de2570de0
BLAKE2b-256 913329f79f5f23de5305fa59dc900658b13f845067c588c8beee092e990bc31d

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 4cab0db075362de8db0c5db01c417a0f98f56152c8f8e81309a211f1b608d776
MD5 cb46afbdaa99b6a272a175dca38dc88c
BLAKE2b-256 c108e2a04a2036a0e9d41b14823e5f20f240bbd518ccdff7180b78936d48097a

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp314-cp314-win_amd64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 41dca20a24ff2b3f44808775551ae029aed70e1349b9d0d47d3517b20e94818f
MD5 1b4886c9d96c5a2dc64a3b8e48f1e378
BLAKE2b-256 96bacfc2313ac87806a69e6ca74f3ed5c3777c2f10b568851032e79f7ceea77c

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp314-cp314-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 08190fa13aeec4c539d7df4de6a17746234d093541d923797d9f7a42c84d19c5
MD5 1d81592e886c023e4db921e6c9d515de
BLAKE2b-256 0236dcc078534a2799c53a100ccf26e10fe5b93416c8fa401de8614718b28389

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3c982a2efaf6d4ce0bb4eb13d6c3e3d7b9d7e0392349abd30e3c0903f710e1a8
MD5 ebb8638e3bf34ed6a6908a7577d940bd
BLAKE2b-256 23f54504571ad097e182a3f4f22dd2f3f6f2c8642e08396a8cdbbd1a280a1209

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 27e348fdd84aca7dbe5382fcf68402af407b5fdb03e509c4873bad6e287b98cf
MD5 5e9446ae5eb2b3714f7a004c88adaa7d
BLAKE2b-256 e1e12316c05b8560d10481a2a7e03fdba2639a1856ca1b315ef99a368cc3f4cc

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 fd51f153930b2a894f2f62ea8012c6c9d70094059c7e1a80ee5b0e09a60717f9
MD5 ddb5cefc7b3ccfd0d9856ee06be389e5
BLAKE2b-256 d31beb56073c6df59cc7a73d65c3b61efecaf0b7000fa4cf59e57e68af6c1d48

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 9987ce877ba785652d35937e982c526143048ba73390be7955915faf44d98da6
MD5 414797268d966bbc66bd4dafd474f987
BLAKE2b-256 50662603059157f4d23d31b3e4cd80dbf472985e34eaf07f2c7e103fd889c4ff

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 af3b680acd8f03b6d33ab28858985ed9dcb846b96d2bb2409797bb005efec350
MD5 528000691f57e19324c8941188cc263f
BLAKE2b-256 f568663d01ca17b4c8dd0437aef20f474d07cc13ef7e67b9f6116ac7509b4c75

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 cafd10cc1c4cdda2a58ad73e1522b4d02217619f209576e8e999849b9bd129a2
MD5 811b4a08b03c569580f1cc4a3695d2f1
BLAKE2b-256 8b19eb6065fdde0f81d21da9b3fef9e78423317c19d3298ed566bd446ed4cc97

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fd3824dd71ffa9fd815b10176f828878cf2450f84b3c3898051ce392a4d6e65f
MD5 32964379d63c60e56a5433469d2fee9b
BLAKE2b-256 726e224166aa016dabb954316d13388c3fe00570d52b3b1b6f633f60d0fb396f

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 a61bd1db468a579636bf3335eb521d9485ebb1bd68bc53500f631e3926de2a29
MD5 c1b4755d0e827f6c767aedecc3be7c7c
BLAKE2b-256 0f6bc78adbd7af6f3478c5d8545b50773566204f45c0f2be674dd722cde62ca1

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 0db4bc17f68b713d72b4f3ae5a625b117e7fc04c6deb36cbd52f7219d35f3fde
MD5 ad127666dd8f4bc69a9cc01fc1ec8302
BLAKE2b-256 2f44c82c49d0e2db82bbc47a658e0f82b1512592dda4f8c1642f72125e99cb2e

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 f1c2aa82848cfdcaedb817b41845e735c843f2af96033fb0c1e7126e47ea7cf4
MD5 a91225b1f171032801aafefe7ff9cf9f
BLAKE2b-256 147b8a68b9a66e3708e2637c3be747d32a020f7097c4b60ce84aa2ac35514818

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 639e839bdea43831b05b37e5e41ce7ad57e13dfd48146a603a2299df2cbf6287
MD5 9c113a6a1ea72d2c5d096123ca1fbec2
BLAKE2b-256 49439855c42c9ba1db927f1939d8f5848d7484bdbacd1e921a15b4e984972ebf

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 bc7103dc0cd75e7ed48f8d59401dcea0c3700397c662d5940e34be577fddf997
MD5 5cbd3e056285d3e5949cecafda0a4ab5
BLAKE2b-256 bdb65e0711f07a6742de680cd1e5e5322cdb25ff8fdfa15a82a950530f7cf948

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 9ab11030772d106464c5ba76c1e856b35eb84141b778a77a4a6956322f88fc3a
MD5 e52a02cf2d899324f81a70ee239faf70
BLAKE2b-256 3e6bccfcb34e755b96c93f35fffc12dcdbc73f9146ef59f0519617edc6402f49

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 93ac7faf110a7112f41676b998c7e1c536997e2a8124b5799aa36608bafa9501
MD5 f75014c091f0f9abc22c2dfd8a6df6b9
BLAKE2b-256 b74b2c68468ab8254e227e51812c80ab5fe95f3eb9be228122de6edba0d090b9

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 14bcb01de1fa842fd80a06c5e6e354b7d0fd231504e86db250da68dcc71a0f83
MD5 53f4295e8ab2843d91737afd36c02255
BLAKE2b-256 25853ab7c4019d290beb90e3bdaf33f72df0782e9e3eab5d334a13eb0eded608

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp310-cp310-win_amd64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 8576aa2bd64ebe001ef9bbb3c9ec7e51b84b9157a45038f57c86e731bf182588
MD5 b633b1db24777dbd3e8d5da8954951b4
BLAKE2b-256 db6c79f5ab755d10ae5a85c1120cd82cec802efa1fc43a97cc5d352c5b3d9fe2

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 2dc2baeab268fa36586ade3463b8a710b6270b7c113b26b2f2838fcbc5bb863f
MD5 713e25b3c59b17aefc90597a89313caa
BLAKE2b-256 407dd2aa7e29290c23ff168eac4139ab32ca1a26d9b0f63f1d4af6ce5cd02c9b

See more details on using hashes here.

File details

Details for the file rusty_tags-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 29649d03a3f97a03bdaa985be37bc97ed89344a78e79977bc4aa57eeb835c540
MD5 06c0f5cbb35fe2b7899953623706bb6e
BLAKE2b-256 5ec3d8efe29e44a060d2511882e68d21d7934e9f7ded28a31dd24933527d7b56

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page