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
+REDRAW
inject 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)