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.6.36.tar.gz (75.5 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.6.36-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded PyPymusllinux: musl 1.2+ x86-64

rusty_tags-0.6.36-pp311-pypy311_pp73-manylinux_2_24_x86_64.whl (1.2 MB view details)

Uploaded PyPymanylinux: glibc 2.24+ x86-64

rusty_tags-0.6.36-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded PyPymusllinux: musl 1.2+ x86-64

rusty_tags-0.6.36-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.6.36-cp314-cp314-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.14Windows x86-64

rusty_tags-0.6.36-cp314-cp314-musllinux_1_2_x86_64.whl (1.4 MB view details)

Uploaded CPython 3.14musllinux: musl 1.2+ x86-64

rusty_tags-0.6.36-cp314-cp314-manylinux_2_24_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.24+ x86-64

rusty_tags-0.6.36-cp314-cp314-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

rusty_tags-0.6.36-cp313-cp313t-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.13tmusllinux: musl 1.2+ x86-64

rusty_tags-0.6.36-cp313-cp313-win_amd64.whl (1.0 MB view details)

Uploaded CPython 3.13Windows x86-64

rusty_tags-0.6.36-cp313-cp313-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

rusty_tags-0.6.36-cp313-cp313-manylinux_2_24_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.24+ x86-64

rusty_tags-0.6.36-cp313-cp313-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

rusty_tags-0.6.36-cp312-cp312-win_amd64.whl (1.0 MB view details)

Uploaded CPython 3.12Windows x86-64

rusty_tags-0.6.36-cp312-cp312-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

rusty_tags-0.6.36-cp312-cp312-manylinux_2_24_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.24+ x86-64

rusty_tags-0.6.36-cp312-cp312-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

rusty_tags-0.6.36-cp311-cp311-win_amd64.whl (1.2 MB view details)

Uploaded CPython 3.11Windows x86-64

rusty_tags-0.6.36-cp311-cp311-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ x86-64

rusty_tags-0.6.36-cp311-cp311-manylinux_2_24_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.24+ x86-64

rusty_tags-0.6.36-cp311-cp311-macosx_11_0_arm64.whl (1.1 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

rusty_tags-0.6.36-cp310-cp310-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.10Windows x86-64

rusty_tags-0.6.36-cp310-cp310-musllinux_1_2_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ x86-64

rusty_tags-0.6.36-cp310-cp310-manylinux_2_24_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.24+ x86-64

File details

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

File metadata

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

File hashes

Hashes for rusty_tags-0.6.36.tar.gz
Algorithm Hash digest
SHA256 917cbc68c92954172142acbdb334521660a7497aff2ea39386ffbcf14eb1facc
MD5 3198b573b3c13bcada2eb6c2e0d49b0f
BLAKE2b-256 33f7eb03e4184564ad612d902dbfaa7f6ee5caa23c21e2cead481aff9b3b632b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 756d3c8c4465c952729dc6552060342c665aea1f90c6e6019ec867f36337d71e
MD5 19dfa7f5da0fa51e851ad51b95b3ae83
BLAKE2b-256 be5f0f9eeb1364729fd1703d757ed43c4816813fb855fe532259444baf9ae4b5

See more details on using hashes here.

File details

Details for the file rusty_tags-0.6.36-pp311-pypy311_pp73-manylinux_2_24_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.6.36-pp311-pypy311_pp73-manylinux_2_24_x86_64.whl
Algorithm Hash digest
SHA256 ba8e6c0be7e187545a9ee0a4749a695b7552d19c24643a39b2521b9c9ebb6751
MD5 b69cc5833c488102d3386f0d3e6adcc8
BLAKE2b-256 3097c9513f4b0e30257f26421c48fb7fbd277d67dc24e54fce136511cdad377d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 a26ef8de458f5b4621dbd658794c806a7f8b5a5dfc122ba062658bddf08354d3
MD5 76143436f6971ef1ab0318506dd4d1a8
BLAKE2b-256 af6b2f2762cdab949049fec61f4f1cb462487d430d277e4526fa3b793726299d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp314-cp314t-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 270320126ed559987c438e48f1d7cee966a3b115ada101fc32437cbfffae4020
MD5 cd8880b9825d1e6e3248b4fb05474118
BLAKE2b-256 faad6a93954111d62c1049ea9922c14e3880bcc389fb345932e85daf61598a44

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 82e3a9a9a1aef113325efa81b01b7d7954b7881b28e5405394f4a7e46ff4acbe
MD5 3681134d4c2ce18f8f00973c36dd2faa
BLAKE2b-256 0c484b379b4534e0a74c96b6c857253bbb29f8f1625f8203248234b11d1f1f88

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 84c97ff36cf4ee39578e2e95ded1fe0d6fd1fa197452142c057e6dbc6d90bc12
MD5 0a0d448fc5bc7a16d9a3ca97ef7514fa
BLAKE2b-256 8be82d2d313f85f5e29ee797592fd7fdacdad0a09e747aaff1009e9d14c35fd4

See more details on using hashes here.

File details

Details for the file rusty_tags-0.6.36-cp314-cp314-manylinux_2_24_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp314-cp314-manylinux_2_24_x86_64.whl
Algorithm Hash digest
SHA256 25d3ba25cb5d527c7d5388e1b9e74d4e7b4283e4efc4284089d1c7e700440c28
MD5 075ed6bcf2df3cb00a354deeeb68a93a
BLAKE2b-256 cdea38955d3be8ff8e4eb845c2f6a36ddc0a87b4cf57b3fd9a2e6afcec39e0ea

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6eff81a325ed732743740870bde782fbfabee65f674d367b5b53ea5f3ffca388
MD5 634bd340ac2205c39c8a224a340d2b7c
BLAKE2b-256 7e99acdeb67801dcb8e69fbaafc6d53ba8da40ceeda55432d011d22a3450f94b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp313-cp313t-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 222bd254584a07aa79ed27a18698c035a4faa604a6c2051894845468afb978e7
MD5 a645e7707ea5e3c2a7f82c439361174a
BLAKE2b-256 db543b34aecdc17498c984f133befa3ac9c629b543c0b2bd63760c091b9bcee7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 c57078341c4b1183e52664495969be19730bdfbdb649e207e103255009ec8930
MD5 5a186deb0697486c7e11000c96f43964
BLAKE2b-256 6351bf024dbeec26ff8d5fcc8e38691c4fa0d6c1917528c023860851042c75d5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 9dd849d399e6a614416d93b190424c43cd4a7a44f82357368f5adb78766d870c
MD5 8b95fc817d752bf6bf1f6306e07a1887
BLAKE2b-256 f66764b94da8d38bd3f0484225ff51d6aa735bf329fce479195f5b6914f74919

See more details on using hashes here.

File details

Details for the file rusty_tags-0.6.36-cp313-cp313-manylinux_2_24_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp313-cp313-manylinux_2_24_x86_64.whl
Algorithm Hash digest
SHA256 a329cdd1665327c3e9ce082ac91b29443b651a1fd4f19315c363b249e6c358ab
MD5 9f35fb102523ed25deaa20102733a26d
BLAKE2b-256 23e50a8f376613361bb2123311a331636dcf5151171138bb00d5be9983497946

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b1f0c19a98852358b420f8cee82af3ff2bad9d58952d4828380feb0f505c8a55
MD5 fdfdba15e6b976a49e225f842fd647a7
BLAKE2b-256 37995e98d8f2db9d8ef654667d1bce5af941c2972fad1214fb6463a5c7f8226d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 316d6deb6ab9d816a56aa5f766e661dc64b79dde0064781dc33163adaaf504a6
MD5 ab85e20669dd4de136c6765b659e3c04
BLAKE2b-256 66c5674f760c8475e796f7f8415d4133f19331ef8116b76e8ecdea552c291583

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 525cd818e59d67620202b692bf471ee4c752d63da25211fa2b1e4abef6c39758
MD5 6111374e308c6698ccbfa49fad233525
BLAKE2b-256 2bfb4c593e6967ad92b5d5f32c3461ce6d0e740954c83411d2e70c674d6b0c0c

See more details on using hashes here.

File details

Details for the file rusty_tags-0.6.36-cp312-cp312-manylinux_2_24_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp312-cp312-manylinux_2_24_x86_64.whl
Algorithm Hash digest
SHA256 2f5f479a78f335a9666cf3fca56fe7fdb0dbded1b9959842038810da61bfe319
MD5 427a5c962170148b63060535e4b1101e
BLAKE2b-256 5308a0223579f2b08470f23e6e7db84d233ec09270faca41ded568e29d23dd23

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fb63f8b20e8752b84436c022f89f203bbb977568dea6900fb1de85a9d688af83
MD5 25e43df0d2ac7ce38b5636db89ee5ab8
BLAKE2b-256 4660d031bdd333e6d7dad418db2e0bfeb2b6d80c97224c08a96db02bba6ebc43

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 bbcd9a1e0c07e835db8c82735bb9652687b925e62010f12f885543b7b905b379
MD5 848cbe1bbc8cdc2e659a9615d0a92c66
BLAKE2b-256 2efd15322d30e41f0c85d65a0449bd2c680d91d52736dbc73861ebf6c7f62ec6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 e05047407b32f82ed87dc733d6a3cda5c87c957ecd77a512666ecece4311f8d5
MD5 2a627ea1404e5b574eca27f01c62ad68
BLAKE2b-256 aa16e36fd700b530c1d01f443108d532defd02573fbdf34ce2427a321853870a

See more details on using hashes here.

File details

Details for the file rusty_tags-0.6.36-cp311-cp311-manylinux_2_24_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp311-cp311-manylinux_2_24_x86_64.whl
Algorithm Hash digest
SHA256 8234dcfe86487359cc0f23ab3f1d54e411e1028e409bfba2685b436c57295d59
MD5 38a9680e91577f43f4d5dd9826ca33e3
BLAKE2b-256 dd083a1bb907a006dac4927b1e23c227eaf520261e6dee8c964818fa34080b61

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 644c38780c9ceac29ba5ce114001078dbab3d383c56748d8868e5c37d7152cf2
MD5 da8ab5b841a88dd8735d085bd7b9f954
BLAKE2b-256 af402abc118fb4a69408d729848234781650de16b96d6727f3a26143d0695f6a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 0d94fd78f28d3461e27f98dce03c878016e3e7e21a9bb8668cb15c5831116bb6
MD5 5b73fd0fef88cbe664f5b98d104fe5dd
BLAKE2b-256 6085d5467225a78fd1a8c20f3867271af7c2c2f8e096fd028fc61b1da51b17d9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b32f301b4a7e360c8a9b11714b765dd84ad8bb95c0187113f8acdbf86a7aecb5
MD5 8fcafc5936fd2f8befd92306a2ba02fd
BLAKE2b-256 348acdbd9d19b10452b0bd39221f6c35edb06a91fda5a583d4922e24297e116e

See more details on using hashes here.

File details

Details for the file rusty_tags-0.6.36-cp310-cp310-manylinux_2_24_x86_64.whl.

File metadata

File hashes

Hashes for rusty_tags-0.6.36-cp310-cp310-manylinux_2_24_x86_64.whl
Algorithm Hash digest
SHA256 d92a0fcb30f4fe66dd45ce24c31c5eee22f6954307d16614b0906ffa0c8dd469
MD5 59cda57a605e0f0982d487c3074f26c7
BLAKE2b-256 69f1c2733ba7d5b24f7bb1f5f048e6ac387a4739ebec92f0da333898e9d3e998

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