Skip to content

Instantly share code, notes, and snippets.

@Atharva-Kanherkar
Last active November 26, 2025 03:57
Show Gist options
  • Select an option

  • Save Atharva-Kanherkar/2c8d15d6219d7800e8ff6c474a2a7358 to your computer and use it in GitHub Desktop.

Select an option

Save Atharva-Kanherkar/2c8d15d6219d7800e8ff6c474a2a7358 to your computer and use it in GitHub Desktop.
[GSOC 2025] : Final Report

Workflows4s — GSoC 2025 Final Report

Author: Atharva Kanherkar

A comprehensive, reproducible summary of my work during Google Summer of Code 2025 for the workflows4s project. This report details the project's objectives, accomplishments, technical architecture, key learnings, and potential future work.


TL;DR — Project Summary

  • Project Goal: Build a minimal, developer-friendly UI and API for workflows4s to enable interactive visualization, runtime introspection, and simple deployment. The primary aim was to provide a tangible, out-of-the-box experience for users to see their workflows in action without a complex setup.
  • Key Outcomes:
    • Tyrian + Bulma UI: A modern, functional frontend built with Scala.js, offering a reactive user experience.
    • Tapir REST API: A type-safe, OpenAPI-documented API for interacting with the workflow engine.
    • Client-Side Visualization: Dynamic generation of workflow diagrams using Mermaid.js, allowing for visual tracking of execution progress.
    • Automated Deployment: A complete CI/CD pipeline using Docker and GitHub Actions to deploy a live demonstration instance on Fly.io.
    • Iterative Development: All features were delivered through a series of focused, well-documented pull requests on the gsoc-2025 branch.

Goals (as defined at project start)

The project was guided by four primary objectives designed to create a complete, demonstrable vertical slice of functionality.

  1. Provide a working UI and API: The initial goal was to establish the foundational modules—a server with a basic Tapir endpoint and a client with a Tyrian UI—to ensure the core technology choices were viable and could communicate effectively.
  2. Enable Workflow Introspection: To make the tool useful, it needed to list available workflow definitions and their running instances. This required creating a type-safe API to expose this data from the core engine to the frontend.
  3. Visualize Workflow Progress: A key feature was to go beyond simple text and JSON. This goal focused on translating the engine's execution trace (WIOExecutionProgress) into a visual flowchart using Mermaid diagrams, making it intuitive to see a workflow's current state.
  4. Deploy for Demonstration: To make the project easily accessible to mentors and the community, the final goal was to package the entire application (backend server and static UI assets) into a single Docker container and automate its deployment to a public URL using Fly.io.

What Was Done

The project was executed through a series of incremental pull requests, each building upon the last.

  1. Initial Scaffolding and Examples (PR #103, #104)

    • Minor repository cleanup was performed to standardize the development environment. A practical "Course Registration" workflow was added, which served as a realistic test case for all subsequent UI and API development, ensuring features were built against a non-trivial example.
  2. UI and API Module Creation (PR #106, #108)

    • The workflows4s-ui module was bootstrapped using Tyrian, a functional programming library for Scala.js. This established the Model-View-Update (MVU) architecture, which simplifies state management. Simultaneously, the workflows4s-web-api module was created using Tapir to define API endpoints. This allowed for a single source of truth for the API contract, shared between the JVM backend and the Scala.js frontend, eliminating the risk of client-server drift.
  3. Core Feature Implementation (PR #114, #119)

    • With the foundation in place, work began on core features. A simple JSON viewer was added to the UI for inspecting the raw state of any selected workflow instance, providing a crucial tool for debugging. The UI code was then significantly refactored for modularity and styled with the Bulma CSS framework to improve layout, readability, and overall user experience.
  4. Deployment Automation (PR #133)

      - This critical phase involved configuring sbt-native-packager to build a containerized version of the application. This process packages the Scala HTTP server and the compiled Scala.js frontend assets into a single, portable Docker image. A GitHub Actions workflow was configured to automatically build this image on every push to the main branch, run tests, and deploy the new version to Fly.io, establishing a full CI/CD pipeline.

  1. Workflow Visualization (PR #151)

    • The final major feature was implementing visualization. The backend was enhanced to provide an endpoint that returns the execution trace of a workflow. The frontend then consumes this data, converts it into Mermaid diagram syntax on the client side, and uses the Mermaid.js library to render it as an SVG flowchart. This approach keeps the server light by offloading the rendering work to the browser.

Pull Requests (Open & Merged)

PR # Title Status Link
151 feat(api and ui): Visualisations Open View PR #151
133 Add Fly.io Deployment & CI/CD Merged View PR #133
119 Refactor UI + Bulma Integration Merged View PR #119
114 JSON Viewer & Simplified Models Merged View PR #114
108 Add Web API Module (Tapir) Merged View PR #108
106 Tyrian-based UI Scaffolding Merged View PR #106
104 Course Registration Workflow Example Merged View PR #104
103 Gitignore Updates Merged View PR #103

Architecture Overview

The system is designed with a clean separation of concerns, leveraging the strengths of the Scala ecosystem across the full stack.

[ workflows4s-core ]
│
▼
[ Tapir API Server (JVM) ] <---- (HTTP API Calls) ----> [ Tyrian UI (Scala.js in Browser) ]
│                                                        │
(Provides workflow logic)                                (Makes API requests)
│                                                        │
▼                                                        ▼
WIOExecutionProgress data ---------------------------> Mermaid syntax generation → Renders SVG

Data Flow:

  1. A user interacts with the Tyrian UI in their browser.
  2. The UI triggers an action, which sends a type-safe HTTP request to the Tapir API Server.
  3. The server uses the workflows4s-core library to execute logic, such as listing workflows or fetching the state of a specific instance.
  4. For visualization, the server sends the WIOExecutionProgress data back to the client.
  5. The Scala.js code in the UI then transforms this data into Mermaid diagram syntax and uses Mermaid.js to render an interactive SVG image.

Deployment: The application is packaged as a single unit where the backend server also serves the static frontend assets (HTML, CSS, and compiled JavaScript).

┌───────────────────────────────────────────────┐
│ Docker Container @ Fly.io                     │
│ ┌───────────────────────────────────────────┐ │
│ │ JVM Process                               │ │
│ │ ├── Tapir API Server                      │ │
│ │ └── Serves Static UI Assets               │ │
│ └───────────────────────────────────────────┘ │
└───────────────────────────────────────────────┘

Lessons Learned

This project provided valuable insights into full-stack application development within the Scala ecosystem.

  • The Power of Shared Contracts: Using Tapir to define the API in a shared module was a game-changer. It made it impossible for the client and server to have mismatched expectations, catching potential integration bugs at compile time rather than runtime. This significantly improved developer ergonomics.

  • Functional UI is Simpler: Adopting Tyrian's functional, message-passing (MVU) architecture for the frontend made state management predictable and easy to reason about. It avoided the complex, error-prone state synchronization issues often found in more traditional imperative UI frameworks.

  • Dockerizing Scala.js Requires Finesse: The biggest technical hurdle was creating an efficient Docker build using sbt-native-packager. Configuring the plugin to produce an optimized, multi-stage build was key. The final setup compiles the Scala.js assets and then copies them into a lightweight, JRE-only final image alongside the backend JAR. This approach, managed within the build definition, kept the final image size small and secure without requiring a manual Dockerfile.

  • Cross-Compilation Demands Discipline: Sharing code between the JVM and JavaScript environments requires careful management of dependencies. We had to be vigilant to ensure that JVM-specific libraries (like certain logging frameworks or blocking I/O clients) were not accidentally included in the Scala.js module, which would cause compilation to fail.


Next Steps

While the GSoC project achieved its goals, there are several exciting directions for future development.

  1. Interactive Workflow Signals: The current UI is read-only. A major next step is to build a UI for sending signals to a waiting workflow (e.g., an "approval" or "payment received" event). This would make the application fully interactive and demonstrate a core feature of workflows4s.
  2. Enhanced UI/UX: The current UI is functional but basic. Future work could include adding pagination and filtering for large lists of workflow instances, as well as improving diagram interactivity with features like zooming, panning, and clicking on a workflow step to view its detailed state.
  3. Stabilize API Contracts: The API currently sends raw data structures. A good next step would be to introduce stable, versioned Data Transfer Objects (DTOs) to create a more robust and forward-compatible API for public consumption.
  4. Real-time Updates with WebSockets: Instead of requiring the user to refresh to see workflow progress, WebSockets could be used to push real-time state updates from the server to the UI, providing a much more dynamic experience.

Reproduce Locally

The recommended development setup uses three separate terminal tabs for a smooth, hot-reloading experience.

First, clone the repository:

git clone https://github.com/business4s/workflows4s.git
cd workflows4s
git checkout gsoc-2025

Terminal 1: Scala.js Frontend Compiler

This terminal watches for changes in your Scala.js code and recompiles it automatically.

# In the root project directory
sbt
> ~workflows4s-web-ui/fastLinkJS

Terminal 2: Scala Backend Server

This terminal runs the backend API server.

# In the root project directory
sbt
> workflows4s-examples/runMain workflows4s.example.api.Server

Terminal 3: Vite Dev Server

This terminal runs the frontend Vite server, which provides the UI and handles hot-reloading in the browser.

# Navigate to the UI sub-directory
cd workflows4s-web-ui

# Install dependencies if you haven't already
npm install

# Start the dev server
npm run dev

Now, navigate to http://localhost:5173/ to see your site. Changes made to the Scala.js source code will trigger a rebuild in Terminal 1, and Vite (Terminal 3) will automatically reload the page.

You can still query the backend API directly at http://localhost:8081. For example:

curl http://localhost:8081/api/v1/definitions

Acknowledgements

I extend my sincere thanks to my mentors, Voytek Pituła and Dave Smith, for their invaluable guidance, detailed code reviews, and unwavering support throughout this project. Their expertise was instrumental in shaping the architecture and ensuring a successful outcome.


References

@chandan9648
Copy link

Really inspiring to see such a clean full-stack implementation in Scala! The clarity of your report makes it super easy to follow your GSoC journey. Great example of how to document and deliver an open-source project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment