Quick start
from almasix.conduit import Component
class Counter(Component): count = 0
def increment(self) -> None: self.count += 1
def render(self) -> str: return "conduit.counter"<!-- resources/views/conduit/counter.prism.html --><div> <h1 wire:text="count">{{ count }}</h1> <button type="button" wire:click="increment" data-loading>+</button> <input type="text" wire:model.live="label"> <span wire:text="label">{{ label }}</span></div><!-- layout -->@conduitScripts@conduit('counter')from almasix.conduit import conduitfrom almasix.prism.helpers import view
def show(): return view("page", {"body": conduit("counter")})Why it can feel like pure JS
Section titled “Why it can feel like pure JS”Conduit optimizes the happy path so typing and toggles do not wait on the network for visual feedback:
- Client bindings —
wire:text,wire:show, andwire:bind:*update from$wire/serverMemo.dataimmediately after optimistic local writes. - Request coalescing — updates/calls within ~16ms merge into one
POST /conduit/update(Livewire-style batching). - Idiomorph-lite morph — patches attributes and keyed children instead of
blindly replacing the root (respects
wire:ignore/wire:key). - Islands —
wire:island/$wire.$island()scopes HTML morph to a region so the rest of the component stays put. .renderless— skip HTML when only server state / events matter.data-loading— v4-style loading hooks for CSS without extra roundtrips.
Use wire:model.live + wire:text on the same property for an input that feels
instant while still syncing to the server.