Framework Comparison

How djust compares to Phoenix LiveView, Laravel Livewire, and HTMX. Make an informed decision for your next project.

At a Glance

FeaturedjustLiveViewLivewireHTMX
Language Python ElixirPHPAny
Framework Django PhoenixLaravelN/A
VDOM Engine {'check': True, 'label': 'Rust'} {'check': True, 'label': 'Elixir'}{'check': True, 'label': 'PHP'}{'check': False, 'label': 'Full swap'}
Client Bundle Size ~64 KB ~30 KB~50 KB~14 KB
Rendering Speed ~0.2ms ~1-2ms~5-10msN/A
VDOM Diff Speed <100μs ~200μs~500μsN/A
WebSocket Required {'partial': True, 'label': 'Optional'} {'check': True, 'label': 'Required'}{'check': False, 'label': 'HTTP only'}{'check': False, 'label': 'HTTP only'}
Form Integration {'check': True, 'label': 'Django Forms'} {'check': True, 'label': 'Ecto'}{'check': True, 'label': 'Form Requests'}{'partial': True, 'label': 'Manual'}
Component System {'check': True, 'label': 'Stateful'} {'check': True, 'label': 'Stateful'}{'check': True, 'label': 'Stateful'}{'check': False, 'label': 'None'}
State Management {'check': True, 'label': 'Decorators'} {'check': True, 'label': 'Hooks'}{'check': True, 'label': 'Properties'}{'check': False, 'label': 'Manual'}
LLM/AI Streaming {'check': True, 'label': 'Built-in'} {'partial': True, 'label': 'Manual'}{'check': False, 'label': 'No'}{'partial': True, 'label': 'SSE only'}
Presence Tracking {'check': True, 'label': 'Built-in'} {'check': True, 'label': 'Built-in'}{'check': False, 'label': 'No'}{'check': False, 'label': 'No'}
Server Push {'check': True, 'label': 'push_to_view'} {'check': True, 'label': 'send_update'}{'partial': True, 'label': 'Events'}{'check': False, 'label': 'No'}
JS Hooks/Lifecycle {'check': True, 'label': 'dj-hook'} {'check': True, 'label': 'phx-hook'}{'check': True, 'label': 'Alpine.js'}{'partial': True, 'label': 'Events'}
File Upload {'check': True, 'label': 'Chunked WS'} {'check': True, 'label': 'Built-in'}{'check': True, 'label': 'Built-in'}{'partial': True, 'label': 'Manual'}
Multi-Tenant {'check': True, 'label': 'TenantMixin'} {'partial': True, 'label': 'Manual'}{'partial': True, 'label': 'Manual'}{'check': False, 'label': 'N/A'}
PWA/Offline {'check': True, 'label': 'PWAMixin'} {'partial': True, 'label': 'Manual'}{'partial': True, 'label': 'Manual'}{'partial': True, 'label': 'Manual'}

Code Comparison: Counter Example

djust (Python)

from djust import LiveView
from djust.decorators import event_handler

class CounterView(LiveView):
    template = """
    <div dj-root>
        <h1>&#123;&#123; count &#125;&#125;</h1>
        <button dj-click="increment">+</button>
    </div>
    """

    def mount(self, request, **kwargs):
        self.count = 0

    @event_handler()
    def increment(self, **kwargs):
        self.count += 1

Phoenix LiveView (Elixir)

defmodule CounterLive do
  use Phoenix.LiveView

  def render(assigns) do
    ~H"""
    <div>
      <h1><%= @count %></h1>
      <button phx-click="increment">+</button>
    </div>
    """
  end

  def mount(_params, _session, socket) do
    {:ok, assign(socket, count: 0)}
  end

  def handle_event("increment", _, socket) do
    {:noreply, assign(socket, count: socket.assigns.count + 1)}
  end
end

Laravel Livewire (PHP)

namespace App\Livewire;

use Livewire\Component;

class Counter extends Component
{
    public $count = 0;

    public function increment()
    {
        $this->count++;
    }

    public function render()
    {
        return view('livewire.counter');
    }
}

// resources/views/livewire/counter.blade.php
<div>
    <h1>{{ $count }}</h1>
    <button wire:click="increment">+</button>
</div>

HTMX (Any Backend)

# Backend (any language)
@app.route("/counter")
def counter():
    count = session.get('count', 0)
    return render_template('counter.html', count=count)

@app.route("/increment", methods=['POST'])
def increment():
    count = session.get('count', 0) + 1
    session['count'] = count
    return f'<h1>{count}</h1>'

<!-- Template -->
<div>
    <h1 id="count">{{ count }}</h1>
    <button hx-post="/increment"
            hx-target="#count"
            hx-swap="outerHTML">+</button>
</div>

vs Phoenix LiveView

When to choose djust:

  • ✓ You're already using Django/Python
  • ✓ You need the fastest VDOM diffing (Rust)
  • ✓ You want Django ORM integration without an Elixir runtime
  • ✓ You prefer Python decorators over Elixir syntax
  • ✓ You need Django ORM integration
  • ✓ Built-in LLM streaming support (StreamingMixin)
  • ✓ Multi-tenant SaaS support (TenantMixin)

When to choose Phoenix LiveView:

  • • You're already using Phoenix/Elixir
  • • You need proven scalability (>2M connections)
  • • You prefer functional programming
  • • You value ecosystem maturity (2019 release)

vs Laravel Livewire

When to choose djust:

  • ✓ 10x faster rendering (Rust vs PHP)
  • ✓ Comparable bundle (~64KB vs ~50KB gzipped)
  • ✓ Real-time WebSocket support (optional)
  • ✓ Sub-millisecond VDOM diffing
  • ✓ You prefer Python over PHP
  • ✓ Built-in presence tracking and live cursors
  • ✓ Server push from background tasks (push_to_view)

When to choose Laravel Livewire:

  • • You're already using Laravel/PHP
  • • You prefer HTTP polling over WebSockets
  • • You value large ecosystem (2019 release)
  • • You need mature UI component libraries

vs HTMX

When to choose djust:

  • ✓ You need stateful components
  • ✓ You want automatic VDOM diffing
  • ✓ You need real-time WebSocket updates
  • ✓ You want form integration (Django Forms)
  • ✓ You prefer less manual wiring
  • ✓ Built-in file uploads with chunked WebSocket transfer
  • ✓ Progressive Web App support (PWAMixin)

When to choose HTMX:

  • • You want framework-agnostic approach
  • • You prefer explicit HTML attributes
  • • You don't need stateful components
  • • You want to enhance existing HTML
  • • You value simplicity over features

Performance Summary

djust ~0.2ms
LiveView (Elixir) ~1-2ms
Livewire (PHP) ~5-10ms

* Benchmarks based on 10,000 renders of a typical dashboard template

Ready to Try djust?

Experience the performance and developer experience of djust. Explore examples or install locally.