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.35.tar.gz (75.8 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.35-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.35-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded PyPymanylinux: glibc 2.17+ x86-64

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

Uploaded CPython 3.14Windows x86-64

rusty_tags-0.6.35-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.35-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

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

Uploaded CPython 3.14macOS 11.0+ ARM64

rusty_tags-0.6.35-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.35-cp313-cp313-win_amd64.whl (1.0 MB view details)

Uploaded CPython 3.13Windows x86-64

rusty_tags-0.6.35-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.35-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

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

Uploaded CPython 3.13macOS 11.0+ ARM64

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

Uploaded CPython 3.12Windows x86-64

rusty_tags-0.6.35-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.35-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

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

Uploaded CPython 3.12macOS 11.0+ ARM64

rusty_tags-0.6.35-cp311-cp311-win_amd64.whl (1.1 MB view details)

Uploaded CPython 3.11Windows x86-64

rusty_tags-0.6.35-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.35-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

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

Uploaded CPython 3.11macOS 11.0+ ARM64

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

Uploaded CPython 3.10Windows x86-64

rusty_tags-0.6.35-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.35-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

File details

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

File metadata

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

File hashes

Hashes for rusty_tags-0.6.35.tar.gz
Algorithm Hash digest
SHA256 49cb3e0e885e83b08a56d854e8005685dba4cb146e64e02368c3b4dd8784bb29
MD5 820afe50470405cf74487b826216d69c
BLAKE2b-256 ad89d5fbec70fe062a92c5ba89bd217f8641f63fa5be80322b824fc5d61c2f08

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 2bb87f14446b092a5ac05527b457f531b855bd381c9c977a2780a99e5a38d011
MD5 2bb38e5b408d14bc6831b0507ad10c4c
BLAKE2b-256 b90ab0e96ae026fa2deee62b90d46b45d5260607f26c99e2e149f1900a2e2681

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ba6c0cb09413ef9c9663b9ab6a585bb8f1846ecd0e553fe15f27f543518a2c2c
MD5 ccf312e881e24a04c87e45d50bb30c3c
BLAKE2b-256 00b35db021258c6b5216310ff212519907bb7e1bbea79bd0aa1e4e0da6d0e25d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 f346aba786290a0f393e6a934de0f1a36798aba55a8b663929b60c17940ceb5a
MD5 db4ceff866f7f8ee32fe4538eb00b0ec
BLAKE2b-256 00f8abca93f974c00263630d1df64da1f54a3e9d949bb8ae796d5bb05e9b884b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp314-cp314t-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 fe4b729f970ede297ee5f9740a55823c6d49d204e53a17252f0805a8aaf05f04
MD5 3bd8e2ed3537d260dce6d729bdc8b90b
BLAKE2b-256 e6f93db89fe7c01837e7b082dc030271b0081d6d4a28696d0f8e8c44d5158104

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 1d93042e8b08d312a6498d45d079183ccb9e40b569700d04f7c56eefb22c8943
MD5 8fbbe213edecf6162ff4418cd18cac46
BLAKE2b-256 0e46cc08269e8bdc0c5647dc1e129741bc246ac4b9a5b32a8c677bb44c6fe082

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp314-cp314-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 47f34a52065b95908fc40888c7c4988cb9378a294e17fca1ae4dbd9ce65a4d6a
MD5 df743af3009a71f27b4aa400f2758ab8
BLAKE2b-256 2b7a3619e38d241d7e3a965b813f82f3ee51db9a36d3483ce8f0d076d5cf0b80

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 3779c2d10d17610a1fdfd68fc2c957e41ab8c27a64a9c91cc0b20f6b4598bea7
MD5 e4e73a8f004e383aa99f3bdd0f4313e7
BLAKE2b-256 2974ab61e7632b637f9269319aed278001ae33b902cb18d463ef16bba10f4e9c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 96458b13df14232ce8f7f22590b3c8b6a26eef796ca92296a15c1496035655cc
MD5 b37bd19173db2a718e5d059680547dbb
BLAKE2b-256 83ccfd30785fef47a80a7ffdb085d6beb5bc2991dff270c920e6017cc9a16203

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp313-cp313t-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 c13f5bec2b2d092c5d3ae9f4345e55034e809c2c3de1b0d0c5557eba98f8c19d
MD5 b137a55c39a965584447e367c6f24979
BLAKE2b-256 96bc1cd76555cf2f1264439d6bd1d697d7dd1de39ce6f17152e5d1a24cbedc61

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 a3c10ca19f87b7358685f37b82f2e8b3eab3a1ccee4ae0f0e06da6bc6f47c97d
MD5 baf58b5e81d7bfa08c8a086792a4af98
BLAKE2b-256 02544433d797e3d555eadca2ec1f9bf1a207106a203af3b3e34f3966da4caae5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b7f8389d88751ea02a879f936e80e4b419db6a9990177959ce5f9e31d603957e
MD5 f3433cbbf6a50e5443da1d11fe1b8cbf
BLAKE2b-256 06e4abafab3a8e0067b0a5b705e51b8e9df483c93d701a109f9c4c0409039cc5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1bd7350c81fa8a4aa85aa8835adda0c4a1f865b2920b88e20e17428343965f81
MD5 daa756595ac55fbef51b280044d2f328
BLAKE2b-256 e55bfadc8047f541b9929a2b49163947420a6b7b6b1d5929ec32df95029efbae

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a545285f496e2e04c25450f4ceec06194194c43a1e1ab830c4f9767b2c05b7f4
MD5 68bcc05d34350049c84ca3a3cfcd9ebc
BLAKE2b-256 6495cdf92a3fe9400a5ba738e0f042fd68e82628f88d4d6e7158cf3721e0b881

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 1ad5460ac0a295d7bae1311875ba053c2d7fe0056fb91f3fac8d3e80e61bed20
MD5 002c1d586606932f29a067589935b3cb
BLAKE2b-256 b778cf4f2580f0cbe4039463f711e78a98a921b3de669638802cdbad878eb023

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 91e21a21389b041ab6106f9d4fc7809dd32848049708989cf1620c5e16c19b00
MD5 602db3e7533da3d5704a627ba19bb848
BLAKE2b-256 3f5397460786e6fd2c5d1a16545f4b46f9ed9f1fbb012ec2d2eab0c3e60af4a9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 c83b8ffc4543b10cc5b951812aad9519d12910309847c3e86077dad45c1734d8
MD5 9473754ff92257d61cbcf394c6a84a64
BLAKE2b-256 ae86a9c71a184f99a8f504778c2c177596c80664c8c6613fcaae317877d89642

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0f4a298fcbe6567c4aeec7ab93d03591b851965d8476955ed7804f1eb80d5ac3
MD5 28850b5de8bde82fa8227ee3b44be834
BLAKE2b-256 7f9478a62c3e69e42a2552f1e8227d9c355cc284290086197ca176dd3edd8e4c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 05f423060c4ea47410477ac1cb2379ccbd555b4ac3d38840d1c9db2649e5f38f
MD5 8cd2fcca2cd11adb313b9980f0879c7c
BLAKE2b-256 2b401e337b49bc498ee3b1414ff069dd4fa413d812e67723773345a42bbcd8c0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 984261bcac6627b4d3661dd07586f82128d2812eb61fa55e7804f97b95378c06
MD5 e1d3bf95de7d66888961e1ab3c08c671
BLAKE2b-256 f7aedd48831caa7179a12f91d569663deaf1463787bcfc94c8a5d44bb315d053

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 cd2bf73832688ea956c949578ca8bf259e70a3a6a6efd2d38b54b30ab5f48bca
MD5 6e67e6d613e0944509e99a069701cab4
BLAKE2b-256 f88938cd50bd19ea25793d5e6d1cc976a1f4982fdd98343a00f542565f7ce991

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8c1a5c9cf81cb283ac229b86ead8a9e1a59728534c1d805333cfdef74219a308
MD5 7a6fee7b9eda5897b5cfe48fb03b3f21
BLAKE2b-256 c9a9ca91a5d0c08d4b9305e1d90849a000448d8840c0f21e25f60c335e6dbe40

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 2e933993f67d15254c6678041f1b30dc31e073de825b25829992474bdd8ae747
MD5 b36c364b44da39af363d555f624b0a60
BLAKE2b-256 16be5e5ccdb74c16ad51dac804c47dab4152149db9498d4e36f9847ce908df05

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 010296bc6f54d476bd61154b02c8f75ba7d29844909b52f03bfaf6e0dceaf102
MD5 cd0ecee593cd720f2e2bde5bd4c8f4f5
BLAKE2b-256 b0323d6d211ceaa420cba4cd0a046bf9dbc12bdcc9213a3be4ae111b526a03f7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for rusty_tags-0.6.35-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 e51e66d8b36d21ad6faca4ec15167bc2f08b03e4af0940800b46686c68d88bd4
MD5 12cdfcd722cafe280db89ade86845188
BLAKE2b-256 59e9ca436ad91627bdbfa8cde6c582bdb84b077a0632e0388305deff397cc3e1

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