Cromponent π now lets your components bind cookies, query-string params, headers and HTTP-auth credentials directly in the method signature πͺβππ and push live HTML over WebSockets with two tiny hooks ππ°οΈ.
Paired with HTMX on the client, that means real-time Raku apps with zero JavaScript π. Below youβll find the new API plus a complete βlive pollβ example. Dive in! πββοΈ
βΈ»
- Why Cromponent? π€β¨
Cromponent glues together Croβs reactive HTTP / WebSocket server and Cro Templates to give Raku developers a component abstraction Γ la modern SPA frameworks β but rendered on the server and streamed as HTML fragments.
The latest release focuses on state & interaction: declarative request-context binding and built-in WebSocket wiring. β€οΈβπ₯
βΈ»
- Prerequisites at a Glance ππ
| Layer | Role | 1-Liner |
|---|---|---|
| HTMX β‘ | Enriches plain HTML with AJAX, SSE & WebSockets via attributes. | hx-put, hx-target, hx-ext="ws", β¦ |
| Cro π§© | Reactive HTTP/WebSocket server & router for Raku. | route { β¦ } |
| Cro Templates ποΈ | HTML-centric templating DSL compiled on first use. | template 'view.crotmp', %data |
| Red ORM ποΈ | DB-agnostic ORM with migrations & relationships. | model Foo { has Int $.id is serial β¦ } |
| Dynamic vars π | $*foo passes per-request context through deep calls. | $*user in our example |
- New API: Context Traits πͺβππ
Any method tagged is accessible becomes an endpoint and auto-binds request data:
method profile( Str :$uuid is cookie, Str :$q is query, Str :$accept is header, Str :$creds is auth ) is accessible { ... } - Zero plumbing π οΈ
- Type-safe input π‘οΈ
- Self-documenting signatures π
Route pattern:
/ComponentName/<idsβ¦>/profile - New API: Automatic WebSockets ππ°οΈ
- Channel key β
method IDS { $!id }groups browsers in the same room. - Re-render hook β
method REDRAW(:$*user is cookie) { $.Str }returns fresh HTML when you redraw $component. -
<|WebSocket>cromponent addshx-ext="ws" ws-connect="/ws"and the htmx-ws extension swaps fragments for you.
- Channel key β
No manual frames, pings or reconnect loops β Cro & HTMX handle all that jazz. π·
βΈ»
- Building a Live Poll π³οΈβ‘
5.1. Router & DB Setup π£οΈ
my $routes = route { red-defaults "SQLite"; PollItem.^add-cromponent-routes; # auto REST π WebSocket.^add-cromponent-routes; # auto WS π get -> 'polls', Str :$*user is cookie = UUID.new.Str { response.set-cookie: :name<user>, :value($*user); template 'polls.crotmp', { :$*user, :@polls = Poll.^all } } } Cro::HTTP::Server.new(:host<0.0.0.0>, :port(2000), :$routes).start; First visit β‘οΈ generates UUID β‘οΈ saves in πͺ β‘οΈ available as $*user.
5.2. Poll Component π
model Poll does Cromponent { has UInt $.id is serial; has Str $.descr is column; has @.items is relationship(*.poll-id, :model<PollItem>); has @.votes is relationship(*.poll-id, :model<PollVote>); method LOAD($id) { Poll.^load: $id } # rebuild method IDS { $!id } # WS room method REDRAW(:$*user) { $.Str } # push update method did-user-vote($who = $*user) { ?@.votes.first: *.user eq $who } method RENDER { β¦ } # the template } 5.3. PollItem Component β
method vote(Str :$*user is cookie) is accessible { :http-method<PUT>, :returns-cromponent } { red-do :transaction, { $!votes++; self.^save; $!poll.votes.create: :$*user; redraw $!poll; # broadcast π $!poll } } HTMX button:
<button hx-put="/poll-item/42/vote" hx-target="closest .poll" hx-swap="outerHTML">π³οΈ Vote</button> 5.4. WebSocket-Enabled Page π₯οΈ
<|Boilerplate(:title('Polls π³οΈ'), :htmx, :style-sheets('/css'))> <|WebSocket> <h6>Logged in as <.user> πββοΈ</h6> <@.polls><&HTML($_)></@> <a href="/polls">All polls π</a> </|> </|> - Generated Endpoints Recap π€οΈ
| Method | Path | Source | |
|---|---|---|---|
| GET | /polls | manual route | β |
| GET | /polls/<id> | manual route | β |
| PUT | /poll-item/<id>/vote | PollItem.vote | β |
| GET | /cromponent-ws | WebSocket | β |
One call to .^add-cromponent-routes β‘οΈ endpoints galore! π
βΈ»
- Key Take-aways π‘
- Context traits (
is cookieπͺ,is queryβ,is headerπ,is authπ) shred boilerplate. -
IDS+REDRAWinject WebSocket magic with two methods. β¨ - Everything lives in one file: model + template + behaviour β still plain Raku, still testable. π§ͺ
Result: back-end-driven UX with instant updates and zero JavaScript. π
βΈ»
- Further Reading π
- π Cromponent β https://github.com/FCO/Cromponent
- π Cro docs β https://cro.services
- ποΈ Red ORM β https://github.com/FCO/Red
- β‘ HTMX β https://htmx.org
- π htmx-ws extension β https://htmx.org/extensions/ws/
- π§ Dynamic vars in Raku β https://docs.raku.org/language/variables#Dynamic_variables
Happy hacking β and may your components stay Crom-pact! π¦π
Top comments (0)