Want to write web apps in Roc? Look no further! Joy is a web platform (think framework) for full-stack web applications. It's Elm/TEA-style and fits perfectly with Roc. Joy compiles to WASM and has a JS-shim which updates the DOM. It's a pragmatic fit for most web applications, with attention to performance and ergonomics.
This release contains the front-end side of Joy. You can pair it with any back-end, and pass in state to your front-end via flags. I'll release one or more back-end platforms which are tailored to work with the front-end, but right now it's 6:42 AM and time to sleep! :sweat_smile:
Here's a full example app which you can clone and modify to get started: Joy TodoMVC
If this is your first time writing web apps in Roc you may want this: https://www.youtube.com/watch?v=GnEmD17kYsE
Have fun and enjoy!
Niclas Ahden said:
Want to write web apps in Roc? Look no further! Joy is a web platform (think framework) for full-stack web applications. It's Elm/TEA-style and fits perfectly with Roc. Joy compiles to WASM and has a JS-shim which updates the DOM. It's a pragmatic fit for most web applications, with attention to performance and ergonomics.
This release contains the front-end side of Joy. You can pair it with any back-end, and pass in state to your front-end via flags. I'll release one or more back-end platforms which are tailored to work with the front-end, but right now it's 6:42 AM and time to sleep! :sweat_smile:
Here's a full example app which you can clone and modify to get started: Joy TodoMVC
If this is your first time writing web apps in Roc you may want this: https://www.youtube.com/watch?v=GnEmD17kYsE
Have fun and enjoy!
Jazz fusion does give me joy :smile:. Great work!
Knower! :smiley:
Hey @Niclas Ahden , I'm playing with Joy right now, and I got the hello.roc and counter.roc examples working, but I ran into a few issues along the way:
watchexec installed, so when running./watch.roc examples/hello.roc, I only got the message: => Serving 'examples/hello.roc' at http://localhost:8000 then the program would stop with Exit(1) but without any error message.watchexec, I ran the same command and got this output:% ./watch.roc examples/hello.roc
=> Serving 'examples/hello.roc' at http://localhost:8000
[EVENT 0] Event
[EVENT 0] Event
[Running: ./build.roc examples/hello.roc]
[Command killed by ForceStop]
The URL gave nothing, so I ended up interrupting the program and starting again. During this third run, it displayed this:
% ./watch.roc examples/counter.roc
=> Serving 'examples/counter.roc' at http://localhost:8000
[EVENT 0] Event
[EVENT 0] Event
[Running: ./build.roc examples/counter.roc]
roc 1.0s
✓ Resolving Dependencies 4ms
<snipped>
✓ ARC 53ms
[Command was successful]
This time I got the "Hello, Roc!" message in the browser. :tada:
Feeling joyful, I interrupted the program, and ran ./watch.roc examples/counter.roc. It seemed to work, but oddly it still displayed "Hello, Roc!". I refreshed the page, I pressed Cmd-Shift-R, I restarted the program, but it always displayed "Hello, Roc!". Suspecting some caching issue, I changed the port by running JOY_WATCH_PORT=8024 ./watch.roc examples/counter.roc and I finally I saw the counter. :plus: 0 :minus:
Note: the counter resets when I refresh the page, I suppose that's normal, but perhaps worth mentionning?
Hope this helps! I'll try the other examples now.
Trying the keyboard.roc example, I'm running into an issue: the page loads but as soon as I type a key on my keyboard, an error appears in the console: function signature mismatch, and the counters remain at 0:
![]()
For logging.roc, I get a weird message when running ./watch.roc examples/logging.roc:
![]()
Seeing this message, I really didn't expect it to work, but I tried anyway, and to my surprise it works fine:
![]()
Just tried the modal.roc example: worked like a charm. No issues at all (other than the caching problem I mentioned earlier, which forces me to use a different port for each example).
For the pointer.roc example, I get a signature mismatch error as soon as I hover over the "Draw here" region:
![]()
For the time.roc example, I get a signature mismatch error after about 1s when loading the page:
![]()
Side-note: the counter should start at 100! :grinning_face_with_smiling_eyes:
Oh if I quickly click on "Calm down" after reload, then no error appears, the button turns to "Get excited!", and clicking the "Remember this moment" button displays "Level 0, reached at 0". But when I click on "Get excited!", I get the mismatch error after about one second and then nothing works anymore.
Well, this was fun. Let me know if you'd like me to run more tests.
Listening to this while coding in Roc brings me Joy.
Thank you @Aurélien Geron for trying it out and all the great feedback!
I'll fix the port errors and refine the README. You wouldn't have run into those issues at all if the instructions were better!
Sadly those app errors are due to incompatibility with newer Roc compiler versions, and I can't move forward due to some compiler bugs right now (https://github.com/roc-lang/roc/issues/10731 and https://github.com/roc-lang/roc/issues/10733). I'm constantly testing new compiler commits and fixing compatibility and reporting bugs, so we just need more time to reach stability :) Bugs are fixed at an alarming rate so it shouldn't be much longer!
To get around this, please build Roc from source from the latest "known-to-work" commit: scratch that, I forgot that I had to patch the compiler, so 94cbed386c51a8739ced3be76e7ab7b84dd22852 (the latest one is always in flake.nix in the repo root).94cbed386c51a8739ced3be76e7ab7b84dd22852 isn't known-to-work. I'll keep an eye on the bugs above and update it when they're fixed!
If you're able to nix develop then you'll get _exactly_ what you need! However, you shouldn't have to adopt nix in order to use Joy, so the long-term goal is of course stability as everything matures :)
And finally, love that Angine de Poitrine song :) It's going in my work playlist!
Fun fact: Angine de Poitrine is named after a specific type of chest pain when your heart doesn't receive enough oxygen, which is what they figured the music sounds like :laughing:
Hahahah, that makes so much sense :joy:
Last updated: Aug 12 2026 at 12:35 UTC