Stream: announcements

Topic: roc-ray 0.9.0


view this post on Zulip Luke Boswell (Aug 06 2026 at 00:26):

Big upgrades have landed in https://github.com/lukewilliamboswell/roc-ray with the 0.9 release

Here's a recording of the ScrewBot demo running buttery smooth at 120fps with hot-reloading.

Screencast from 2026-08-06 10-13-16.webm

view this post on Zulip Jake Brownson (Aug 06 2026 at 21:29):

Thanks for your work on this Luke.

For my Puri GUI framework demo, I asked my LLM to add clipboard support and it went off and did a slightly crazy hack to bring in RocRay with additions. After updating to 0.9 and moving multi-click recognition into Puri, the local adapter is down to three additions:

These are all features of raylib so I think it'd make sense to just expose them through the platform? Something feels a bit off about all of this to me somehow, but I'm trying to open my mind to it. I'm accustomed to composing things to solve problems like this. I understand the benefits of having a clear line of what a Roc program can do, but I wish platforms were more first-class and could be composed/parameterized. I feel awkward asking for particular things to be added vs just composing them on to what has been chosen to packaged up by the platform author. It probably makes a lot of sense to have the option of a platform that doesn't expose clipboard for security reasons. I don't see that as a bug or missing feature in general, but for my app I'd like to have it.

view this post on Zulip Luke Boswell (Aug 06 2026 at 21:36):

I hadn't thought of these, good ideas :thumbs_up: I'll add them later today. There was something else I wanted to add too, so if I can remember what that was I'll roll that in as well.

It's definitely an experiment to see how we go - Roc's platform abstraction is pretty unique. I'm not sure the best way to evaluate what should live in the platform and what should be something I encourage people to fork and extend for themselves.

view this post on Zulip Jake Brownson (Aug 07 2026 at 04:15):

This question may be more appropriate in a broader channel, but in my demo Todo app I have a file called RocRayInput.roc. It translates rr.Host and rr.Keys into Puri’s platform-independent events. The translation is pure and conceptually belongs in the reusable puri-rocray package, not inside the Todo application. However, an ordinary package cannot import types or modules from the application’s selected rr platform.

Would it make sense for RocRay’s public data types and pure helpers to live in a companion ordinary package that both the RocRay platform and puri-rocray could depend on? Is that a pattern platform authors should generally consider for public types that reusable packages may need to reference?

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

I think the answer is yes... but it's not really been tried before. The concept for cross-platform packages has been floating around but we haven't seen much beyond the http package.

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

I forgot to make the changes from above earlier. I could try and split the types out and see if I can publish the types in package alongside the platform.

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

I'm not sure where the split is or how it would feel for the downstream app/package authors. But I guess its worth a try. We might find something worth modifying in roc's design

view this post on Zulip Jake Brownson (Aug 07 2026 at 04:20):

My concern isn't cross-platform packages, but I'm building tooling to connect my backend-independent GUI model to roc-ray that then would be used in an application that chooses that backend.

No rush on the other changes. I'm just having fun. I tried going back to Rust to work on my actual project but I keep thinking about Roc :)

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

I'm not sure I follow... if it's not a cross-platform package you are thinking of

view this post on Zulip Jake Brownson (Aug 07 2026 at 04:32):

Puri is designed to be backend (i.e. platform) agnostic, but even if it weren't I wouldn't be able to reference rocray types from it. So imo it's not about having cross-platform packages, but packages that reference platform types even if they're only designed to assist with one platform.

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

I think I might need to experiment and build something to try it out...

Puri can definitely use other packages types, just like a platform package can use other packages types -- so they can both depend on and share a common generic.Keys type

view this post on Zulip Jake Brownson (Aug 07 2026 at 04:38):

yeah, that would be one solution, to make a habit of putting types and pure functions in a separate package

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

I finally remembered what I wanted to add... generating images and videos by recording frames and then encoding that to a file in whatever format you need.

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

The use case I had in mind was rendering a nice diagram or maybe a moving visualization

view this post on Zulip Luke Boswell (Aug 07 2026 at 07:36):

Claude can make sharing links for things, here is a demo of the new Capture features
https://claude.ai/code/artifact/8cdf3963-650d-478c-bded-0fb75e00ae24

Or if the above doesn't work... a capture of a moving graph exported as WebM :grinning_face_with_smiling_eyes:
Screencast from 2026-08-07 17-34-42.webm

view this post on Zulip Luke Boswell (Aug 07 2026 at 08:32):

roc-ray previously had an update! and I think I want to bring it back, I want to take all the slow things off the thread that is drawing and calls Roc and I can't think of a better way to do that.

view this post on Zulip Romain Lepert (Aug 08 2026 at 08:31):

Jake Brownson said:

This question may be more appropriate in a broader channel, but in my demo Todo app I have a file called RocRayInput.roc. It translates rr.Host and rr.Keys into Puri’s platform-independent events. The translation is pure and conceptually belongs in the reusable puri-rocray package, not inside the Todo application. However, an ordinary package cannot import types or modules from the application’s selected rr platform.

Would it make sense for RocRay’s public data types and pure helpers to live in a companion ordinary package that both the RocRay platform and puri-rocray could depend on? Is that a pattern platform authors should generally consider for public types that reusable packages may need to reference?

I want to echo Jake's concern.

In terrocotta I have the same problem, and it is not trying to be cross-platform. Terrocotta can't depend on roc-ray so it can only abstract over structural types/functions that will then unify with roc-ray's types/functions when the user app puts things together.

In particular, since 0.9.0 FontResource has become nominal.

FontResource :: Box(U64)
Font : [DefaultFont, LoadedFont(FontResource)]

load_font! : { path : Str, size : I32 } => { font : FontResource, err : U8 }

Since Terrocotta can't depend on nominal FontResource, it can't use it in its API.
So user can load a font = load_font!("path/to/font", 16) but can't pass it to any terrocotta API. So terrocotta can only work with default font...

So I believe, the roc-ray platform should only define structural API, and a companion roc-ray-types package can define a Nominal API on top if need be. Then Terrocotta can import and work with the nominal types.

view this post on Zulip Luke Boswell (Aug 09 2026 at 11:54):

If anyone is interested, I've been experimenting with a new API for roc-ray in this branch

https://github.com/lukewilliamboswell/roc-ray/tree/spike/elm-architecture

The core idea is introducing a pure update to the API to decouple slow tasks from the fast roc/raylib render loop which runs in a single thread. That lays a nicer architecture for adding features like reading from files and networking.

I need to sit and experiment with it more, but it's starting to feel pretty good.

view this post on Zulip Luke Boswell (Aug 09 2026 at 11:55):

That also includes a supporting types package where all the core types for roc-ray live so other packages could depend and build upon those.

view this post on Zulip Romain Lepert (Aug 10 2026 at 07:42):

This looks great.

view this post on Zulip Luke Boswell (Aug 10 2026 at 07:43):

Unicode package is quite mature now, so we can totally do something there probably

view this post on Zulip Romain Lepert (Aug 10 2026 at 08:06):

font metrics and glyphs must happen on the roc-ray side

FontMetrics := {
    base_size : F32,
    glyphs : List(GlyphMetrics),

   # codepoint → glyph index mapping
    get_glyph_index : FontMetrics, U32 -> U32

}

GlyphMetrics : {
    advance_x : F32,
    offset_x : F32,
    offset_y : F32,
    width : F32,
    height : F32,
}

then unicode package can give the codepoint. Then where does measure(font, config, text) live ? Not unicode because is has no notion of font. roc-ray only if roc-ray is okay with depending on unicode. Otherwise in user code like terrocotta

view this post on Zulip Luke Boswell (Aug 10 2026 at 08:09):

i think I may be able to cheat a little and have this be an "action" the API is still pure for the user but the platform can call the effectful host parts under the hood

view this post on Zulip Luke Boswell (Aug 10 2026 at 08:10):

idk though because I guess the next thing is the user will want to use the layout information

view this post on Zulip Luke Boswell (Aug 10 2026 at 08:11):

do you think it's an issue if UI layout stays in render?

view this post on Zulip Romain Lepert (Aug 10 2026 at 08:12):

shouldn't this metrics buildup happen on Font.load!() which is usually during init! ?

then font has a handle and the metrics/glyphs

view this post on Zulip Luke Boswell (Aug 10 2026 at 08:17):

Good ideas. I've got to head out soon but can poke at it again tomorrow

view this post on Zulip Romain Lepert (Aug 10 2026 at 08:20):

Luke Boswell said:

do you think it's an issue if UI layout stays in render?

I wonder. update is to update the Model. Model update needs layout solved to resolve user interactions (to update which element is focused, i need to know user clicked on what ?) so it feels like layout should be in update.
https://github.com/obust/terrocotta/blob/main/package/Program.roc#L144

view this post on Zulip Romain Lepert (Aug 10 2026 at 08:22):

since render! : Model, Draw.Frame => Try({}, [Exit(I64), ..]) does not modify the model, then if i do layout in render!, how do i update the model focused/hovered/drag/scroll state ?

view this post on Zulip Luke Boswell (Aug 10 2026 at 08:41):

Yeah I think the general shape is layout once per update, retain that in the model for comparing on the next update, and so we need to find a way to make that pure (by moving the font stuff around).


Last updated: Aug 12 2026 at 12:35 UTC