Stream: show and tell

Topic: Rocci


view this post on Zulip Nils Hjelte (Aug 23 2026 at 01:17):

Hello!

I want to showcase Rocci, my exploration into roc and datastar (that has exploded into something much bigger than originally planned). I tried using Roc a little bit with the old syntax and Excersism setup, but had some issues with compilation and also saw that major syntax changes were coming, so I put that aside. I really like the direction of the new syntax and programming model, and I am exiting that the zig compiler has reached this point in such a short time.

And not being previously familiar with datastar, but very intrigued by the architecture after hearing the podcast and watching some presentations!

And I also had some spare time now, so it was a good opportunity to explore using roc and datastar.

And it kind of worked out of the box, so then I had two questions:

And this also coincided with heavily discounted grok-4.6 usage for a week, and I have been experimenting pretty heavily with agents, and am overall very impressed with the rate of progress for models and harnesses.

Anyway, in the end I have built a templating language on top of roc, extended it to express datastar driven backend. And then I experimented even more with extending this to a custom markdown language. And have used all this to build a website that demonstrates and showcases what has been built. I have done experiments with interactive document formats before, so that fits into this.

Right now I call the project Rocci, which is also the name of the template language, and Rocdown is the markdown format.

I have barely looked at the code at this point, been so busy getting demonstrator working.

The docs are also mainly vibe-documented, with manual steering and some manual edits, sorry have not proofread properly.

And the syntax in general is very much a moving target.

Hope to be able to spend more time on this going forward.

Ah didnt realize until now there was a rocci bird thing with same name. It is a project name for now, will see what happens.

Big thanks to the Roc community, and I hope you find this interesting, and I am grateful for feedback.

Going to bed now, good night! Will have limited time tomorrow, family time and meeting some friends as well.

https://rocci.dev
https://github.com/koliyo/rocci

view this post on Zulip Karl (Aug 23 2026 at 03:36):

How does datastar architecture fit in with desktop apps, compare to electron/tauri/etc?

I'd be interested in whatever conclusions you reach on this front. I've briefly looked into HTMX and to a lesser extent into Datastar and they're really similar to mid 2000s apps in general and RoR Turbolinks more specifically. They're good for avoiding the need to coordinate state across the connection and for people that don't want to write JS they provide a means to get some interaction and...that's about it AFIAK. It's not that I don't think apps can be built this way (I've done it), I just don't get the hype.

view this post on Zulip Luke Boswell (Aug 23 2026 at 04:03):

This looks really cool. It's nice to see the webserver and SSE working nicely and to hear Roc worked out of the box for you :smiling_face_with_hearts:

$ PATH=/home/lbw/roc_nightly-linux_x86_64-2026-08-21-90da19f:$PATH   cargo run -q -p rocci-cli -- run examples/rocci/custom/snake --no-window

Screenshot from 2026-08-23 14-01-44.png

view this post on Zulip Luke Boswell (Aug 23 2026 at 04:04):

Nils Hjelte said:

I'm not sure ... there is a lot of experimentation to do I think. This conversation might have something helpful in it for you #API design > Designing a DSL in Roc @ 💬

Specifically I suspect you could have a HTML parser which validates at compile time the template strings.

view this post on Zulip Luke Boswell (Aug 23 2026 at 04:13):

Nils Hjelte said:

If you haven't seen my https://github.com/lukewilliamboswell/roc-ray/ platform, that is basically the Elm architecture for graphical desktop apps, init! update! and render!. I don't plan to add support for the web anytime soon even though it should be possible (I just don't have the bandwidth right now).

I could see datastar fitting into an electron shaped thing (possibly using a fork of basic-webserver or something more tailored for that). If you had a usecase that very specifically needed a cross-platform (including web) support and accessibility was really important maybe the performance tradeoff of bundling a browser engine is worth it.

Some prior art I've used a little is https://wails.io/

I'm not sure how mature the desktop GUI frameworks are from an accessibility perspective (I haven't looked or have much experience in this domain) but I would assume with Roc it will now be much easier for someone to build a nice framework like GUI experience that does all that.

view this post on Zulip Luke Boswell (Aug 23 2026 at 04:31):

Nils Hjelte said:

Right now I call the project Rocci, which is also the name of the template language, and Rocdown is the markdown format.

Riffing off the general bird themes we seem to have going around, this project makes me think of a bird's nest for some reason. Like maybe its a home for roc in the world of web frameworks?

I got carried away brainstorming... here's an idea for you

view this post on Zulip Luke Boswell (Aug 23 2026 at 04:46):

Also somewhat related is @Isaac Van Doren's project https://github.com/isaacvando/rtl

I don't think he's updated that to latest Roc, but I know Isaac spent a lot of time thinking about templates and ideas around that.

view this post on Zulip Isaac Van Doren (Aug 23 2026 at 04:53):

I gave a talk about it if you’re interested https://youtu.be/VXQub6U_BUM

view this post on Zulip Isaac Van Doren (Aug 23 2026 at 04:54):

I should update it to the latest roc!

view this post on Zulip Isaac Van Doren (Aug 23 2026 at 04:55):

I’m building a new hypermedia driven app at work right now (in Rust) and will probably end up using Datastar down the line there. It is very compelling!

view this post on Zulip Nils Hjelte (Aug 23 2026 at 07:07):

Thanks for comments, yeah I realize many people are exploring similar things. It is interesting to explore what the level of opinionation for a stack/framework does for developer experience, in terms of enabling a common structure and consistency, while on the other hand also putting constraints on how things should be done.

I see a few main directions with templating:

There are many who dislike working with HTML/XML directly, and custom syntax can be very appealing, and the type saftey bit is super strong argument for it.

Thanks for link to presentation, will definitely check it out!

I personally think the JS style tagged template literals could be interesting for roc itself, and could benefit from comptime integration and type checking. I assume this has been discussed, perhaps related to the discussion regarding the multiline string syntax in roc (?).

Rocci as name is primarely I needed A name for the project, and how I arrived at it was that I was looking at tauri for desktop integration, and then it was roc+tauri -> rocci. (I definitely saw rocci-bird at some point, so that might have been lingering in the back of my mind, but did not realize until now)

I did the whole "e2e" demo with domain name etc as a bit of an exersice to explore all the parts to put it together.

I'll prioritize exploring alternative naming ideas if this is a bit too close to existing roc naming.

Otherwise I am going to focus more on the desktop app side of things, and explore some ideas around this.

view this post on Zulip TeaDrinkingProgrammer (Aug 23 2026 at 12:20):

Luke Boswell said:

Nils Hjelte said:

If you haven't seen my https://github.com/lukewilliamboswell/roc-ray/ platform, that is basically the Elm architecture for graphical desktop apps, init! update! and render!. I don't plan to add support for the web anytime soon even though it should be possible (I just don't have the bandwidth right now).

I could see datastar fitting into an electron shaped thing (possibly using a fork of basic-webserver or something more tailored for that). If you had a usecase that very specifically needed a cross-platform (including web) support and accessibility was really important maybe the performance tradeoff of bundling a browser engine is worth it.

Some prior art I've used a little is https://wails.io/

I'm not sure how mature the desktop GUI frameworks are from an accessibility perspective (I haven't looked or have much experience in this domain) but I would assume with Roc it will now be much easier for someone to build a nice framework like GUI experience that does all that.

This reminds me of Hyperview, which was I was introduced to via the excellent Hypermedia Systems book. Hyperview allows you to create apps with hypermedia, by generating a hypermedia client and communicating your custom components over the web, so it kind of sends React Native components to the client from the server.

view this post on Zulip Richard Feldman (Aug 23 2026 at 13:36):

so for templating, you can do something like this:

button = |{ text, title ?? "" }|
    \\<button, title="${title}">${text}<button>

however, that won't get you html escaping on the text or html-and-quote escaping on the title

view this post on Zulip Richard Feldman (Aug 23 2026 at 13:42):

but what you can do is make a custom type named something like Html which has from_interpolation and then does automatic things like:

view this post on Zulip Richard Feldman (Aug 23 2026 at 13:43):

that said, I suspect that approach would lead to a good amount of unnecessary escaping, which is very undesirable from a performance perspective.

view this post on Zulip Richard Feldman (Aug 23 2026 at 13:46):

the trouble is that if I use string interpolation like this to nest some html inside some other html, each interpolated value comes in as a plain Str, meaning we've lost the information that it had already been escaped

view this post on Zulip Richard Feldman (Aug 23 2026 at 13:46):

so we have to escape it defensively - creating duplicated work

view this post on Zulip Richard Feldman (Aug 23 2026 at 13:49):

if we wanted to prevent that, we'd either have to make it so that string interpolation supported accepting values that aren't strings (possible, although there are downsides) or else have a separate template syntax (also possible, also has downsides)

view this post on Zulip Richard Feldman (Aug 23 2026 at 13:50):

the duplicated work can already be avoided using a composable DSL for building html, but unfortunately that also has performance downsides compared to templates because it requires more allocations to store an intermediate tree structure :sweat_smile:

view this post on Zulip Isaac Van Doren (Aug 23 2026 at 13:55):

If you want to nest some html inside of other HTML you actually need a way to tell the template language to not escape the inner HTML snippet at all. Could you have another custom typed called UnescapedHtml whose from_interpolation method doesn’t escape?

view this post on Zulip Jasper Woudenberg (Aug 23 2026 at 17:56):

Richard Feldman said:

the duplicated work can already be avoided using a composable DSL for building html, but unfortunately that also has performance downsides compared to templates because it requires more allocations to store an intermediate tree structure :sweat_smile:

I think it depends on the API for the builder. For the Html-builder in Jay I'm producing a flat list of open tags, close tags, text content, and attributes. I hope that will ameliorate the performance problems somewhat. It'd be equally possible to write directly to a string or list of bytes if you don't need to manipulate it anymore after (not the case for Jay).

view this post on Zulip Richard Feldman (Aug 23 2026 at 18:04):

interesting! Maybe should be another topic, but what about nested things? How are they represented?

view this post on Zulip Jasper Woudenberg (Aug 23 2026 at 18:16):

Suppose you have this Html: <a href="foo">Hello, <b>world!</b></a>

It's represented equivalent to: [Open("a"), Attr("href", "foo"), Text("Hello, "), Open("b"), Text("world!"), Close("b"), Close("a")].

Which depending on what you do with it afterward is not as nice as a tree-structure, but if you only need to render it then it's fine.

view this post on Zulip Jasper Woudenberg (Aug 23 2026 at 18:18):

It now occurs to me you might mean what it's represented like in the API. I've made some changes, in particular to attributes, but this example still communicates the idea reasonably well:

import Html exposing [html, attr]

page : Html
page =
    html.body(
        attr,
        html.h1(attr, "Header text!")
            .a(attr.href("./other-page.html"), "click me!"),
    )

Every method call essentially appends one or more items to the list representation.

view this post on Zulip Richard Feldman (Aug 23 2026 at 18:44):

ahh gotcha! Have you considered not materializing the intermediate representation and instead appending string bytes? I think that would be even faster :smile:

view this post on Zulip Jasper Woudenberg (Aug 23 2026 at 20:01):

Yeah, only reason I'm not doing that is because Jay requires some limited manipulation of the Html after it's created (in particular: replacing certain tags with custom Html).

I might still introduce a nested Insert(Html) tag to allow that to happen without copying, so then I'd still have nesting of a sort.

view this post on Zulip Romain Lepert (Aug 23 2026 at 20:34):

Jasper Woudenberg said:

It now occurs to me you might mean what it's represented like in the API. I've made some changes, in particular to attributes, but this example still communicates the idea reasonably well:

import Html exposing [html, attr]

page : Html
page =
    html.body(
        attr,
        html.h1(attr, "Header text!")
            .a(attr.href("./other-page.html"), "click me!"),
    )

Every method call essentially appends one or more items to the list representation.

In terrocotta I do the same thing to go from nested to flat list except i combine (prepend/append) Iter(Element).

This way, instead of the children element chaining I can use a list of children elements which looks more straighforward.

It would then look like:

page : Html
page =
    html.body(attr, [
        html.h1(attr, "Header text!")
        html.a(attr.href("./other-page.html"), "click me!")
    ])

See this architecture.md for overview and here for the iterator combination.

Since in most UI tree has a fixed children count known at compile time I think the roc compiler can optimize away the intermediate list allocation (though I have never checked :smile:).


Last updated: Sep 03 2026 at 15:16 UTC