Workflows4s Web UI: OSS Full Stack App Ready for Production
Today I’m glad to announce Workflows4s Web UI — a new milestone for the Workflows4s project and the result of four months of work and collaboration across the ecosystem.
This post is both a release announcement and a case study — I want to share what we’ve built, but also how we’ve done it and why it matters beyond the Workflows4s context.
What It Is
Without diving too deep into the details, the Web UI is exactly what it sounds like — a web app that lets you browse, inspect, and interact with workflows. Below is a demo video, but you can also try a live instance and read the docs.
It’s powered by an HTTP API that can also be used independently — for example, to build custom UIs, automation scripts, or other tools.
How It Happened — The Magic of Cooperation
While this release is an important milestone for the project itself, what makes me especially happy is how it was built. It was a true collaboration between people from different corners of the Scala ecosystem:
- Atharva Kanherkar — built the initial foundation during this year’s Google Summer of Code.
- Kannupriya Karla (on behalf of Scala Center) — organized this year’s GSoC, making our participation possible. It’s a lot more work behind the scenes than it might look!
- David Smith — co-mentored the project with me and filled in my gaps in frontend development.
- Watson Dinh — helped us implement more advanced functionality, like backend support for workflow signals.
Together we built over 20k lines of code, coordinating through chats, weekly calls, and code reviews — just like a real team.
If you’re curious about our GSoC experience, you can read more in our initial post or in Atharva’s halfway recap.
How It Works — A Real-World Scala.js Example
This project was particularly interesting for me because my previous experiences with Scala.js were… mixed.
Every time I tried it in the past, it felt like more pain than gain — mostly due to how messy it was to deal with the broader JS ecosystem (bundlers, libraries, component frameworks, etc.).
This time, I decided to give it one final chance to check if we can use Scala.js without pain, for a non-toy project? Spoiler: we can.
Here’s the approach and tech stack that made it work.
Vite as a Bundler
Using Vite was a breath of fresh air compared to my earlier experiences with scalajs-bundler
or Webpack. The credit goes to a few things:
vite-plugin-scalajs
makes integrating a Scala.js project into both the dev loop and production build trivial.- It needs almost zero configuration.
- It’s a modern, mainstream tool actively maintained and loved by the JS community.
In short — it just works. And that’s not something I could say before.
CSS Framework Instead of Component Libraries
Disclaimer: I want to have as little to do with CSS as possible. I prefer my code to stay high-level and look okay out of the box without customization.
In the past, I used scalajs-react
hoping to leverage React’s “rich ecosystem”, e.g. Semantic UI React
. That was a trap — while React does have a massive ecosystem, using it from Scala.js lead to an endless stream of pain.
This time I took a different route: Tyrian for the frontend logic, paired with Bulma for styling. You could easily replace them with other tools, eg. Laminar and Bootstrap — the core idea is the same:
Use a Scala-native library for HTML and state management, and a pure CSS framework for styling.
Just attach pre-made CSS classes to your elements, and things look decent immediately.
Sure, you lose the built-in “smart” behavior that component libraries provide (like state tracking or clickability), but those are trivial to implement yourself — and avoiding foreign JS code is a huge win in the long run.
Tapir for the API
Tapir has long been my go-to tool for exposing HTTP APIs — but this was the first time I used it from Scala.js as well.
And it truly delivers on its promise: shared endpoint definitions make API consumption feel just like RPC calls, with no boilerplate and no surprises.
Deployment — The Big Picture
What’s great about Workflows4s is that it’s not just a library — it also comes with an example project that’s now a fully functional full-stack app.
This app is automatically deployed to Fly.io via CI/CD, forming the demo you saw earlier. The process is a bit complex, but it becomes straightforward once you see how the pieces fit together:
- Scala.js compiles Scala sources into JavaScript.
- Vite bundles the generated JS with dependencies into a deployable app.
- sbt embeds the bundle in a Scala artifact as resources, so it can be reused by other projects (this artifact also exposes a Tapir endpoint to serve the assets).
- The example project combines this UI bundle with the API module and serves them together.
sbt-native-packager
builds a Docker image.- GitHub Actions deploy that image to Fly.io.
It’s a nice demonstration that building and deploying a full-stack Scala app can be a clean, fully automatic and reproducible process. Without any advanced custom scripting.
What’s Next?
The current version is just a baseline for future improvements. We’ve already created almost a dozen GitHub issues — many of them labeled as good entry points for new contributors. If you’d like to work on a real, useful full-stack Scala project, take a look and reach out — I’ll be happy to assist along the way!
And if contributing isn’t your thing, that’s perfectly fine too. I hope this new UI adds real value to your projects — and if it does, we’d love to hear your feedback, good or bad!
Summary
This release matters beyond Workflows4s because it’s one of the first open-source Scala.js applications ready for use — showing that the ecosystem has quietly matured. The development and tech stack is both practical and pleasant: shared models, type-safe APIs, and a modern UI all living in one codebase. It’s a small but real proof that Scala.js is not an experiment — it’s ready for real-world software.
And Workflows4s is one step closer to becoming a mainstream workflow solution!