wires
Version, currently main branch1 version
- main branchlatestJun 14, 2026
github.com/garyhe0780/wires
server-driven live components for Crystal and Kemal. Inspired by Hotwire, Phoenix LiveView, and Laravel Livewire.
Installation
# Add this to your shard.yml
dependencies:
wires:
github: garyhe0780/wires
branch: mainmain is a branch, not a release, so this tracks it rather than pinning a version.
Then run:
shards installshard.yml
- Crystal
>= 1.20.2- License
- MIT
- Author
- gary
- Targets
clockfrom examples/clock/app.crwiresfrom src/wires.crlayoutfrom examples/layout/app.crcounterfrom examples/counter/app.crtargetedfrom examples/targeted/app.crdashboardfrom examples/dashboard/app.crdocs_sitefrom examples/docs_site/app.crresilientfrom examples/resilient/app.cruser_cardfrom examples/user_card/app.crnavigationfrom examples/navigation/app.crcontact_formfrom examples/contact_form/app.crreadonly_streamfrom examples/readonly_stream/app.crstatic_componentfrom examples/static_component/app.cr
Dependencies
Runtime Dependencies
- kemal*github: kemalcr/kemal
README
Crystal Live
Server-driven live components for Crystal and Kemal. Inspired by Hotwire, Phoenix LiveView, and Laravel Livewire.
Crystal Live keeps all component state on the server, renders HTML with Declarative Shadow DOM for style isolation, and streams updates over WebSocket using the <?marker?> / <template for> patch protocol.
Installation
Add to your shard.yml:
dependencies:
wires:
github: your-org/wires
Then run shards install.
Quick start
require "kemal"
require "crystal_live"
class Clock < CrystalLive::LiveComponent
def initialize(session_id : String)
super("clock", session_id)
spawn { loop { sleep 1.seconds; push_update } }
end
def render : String
"<p>#{Time.utc.to_s("%H:%M:%S")}</p>"
end
end
CrystalLive::KemalExtensions.mount!
get "/" do |context|
session_id = CrystalLive::KemalExtensions.ensure_session_id(context)
CrystalLive::KemalExtensions.page_html("Clock", Clock.new(session_id).marker_html)
end
Kemal.run
Registry macros
register_live_component :clock, Clock
get "/" do |context|
session_id = CrystalLive::KemalExtensions.ensure_session_id(context)
live_component :clock, session_id
end
Configuration
CrystalLive.configure do |config|
config.ws_path = "/live"
config.stream_path = "/live/stream"
config.heartbeat_interval_ms = 30_000
end
CrystalLive::KemalExtensions.mount!
page_html embeds window.CrystalLiveConfig for the polyfill automatically.
Set config.debug = true to log WebSocket/SSE protocol activity on server and client.
See CHANGELOG.md for release history.
Examples
crystal run examples/static_component/app.cr
crystal run examples/clock/app.cr
crystal run examples/user_card/app.cr
crystal run examples/dashboard/app.cr
crystal run examples/counter/app.cr
crystal run examples/contact_form/app.cr
crystal run examples/targeted/app.cr
crystal run examples/readonly_stream/app.cr
crystal run examples/resilient/app.cr
crystal run examples/layout/app.cr
crystal run examples/docs_site/app.cr
Documentation
Run the documentation site locally:
crystal run examples/docs_site/app.cr
# open http://localhost:3000/docs/
Development
crystal spec
License
MIT
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This branch
- Branch
main- Seen
- Jun 14, 2026
- Crystal
>= 1.20.2- Indexed
- yes
Dependents
No indexed shard depends on this one yet.
Repository
github.com/garyhe0780/wires
Metadata
- Created
- Aug 12, 2026
- Updated
- Aug 15, 2026
- Synced
- Aug 15, 2026
- Versions
- 1