UI/UX Improvements to the Crossflow Diagram Editor

Contributor: Zhen Wan

Mentors: Michael Grey and Aaron Chong

Link to repository: open-rmf/crossflow

Link to Demo Video: Interop SIG, 06 August 2026: Google Summer of Code for Open-RMF

Link to Demo Code: GitHub - ArizmendiWan/hotel-bot-demo: Crossflow orchestration demo for two RMF robots and two hotel elevators · GitHub

Project overview

Crossflow is an open-source reactive programming and workflow engine built in Rust. It can coordinate asynchronous services and express complex control flow, including parallel branches, synchronization, races, cycles, and reusable hierarchical workflows. Its web-based Diagram Editor provides a visual interface for creating, configuring, running, and inspecting these workflows.

My project focused on improving the overall usability of the Crossflow Diagram Editor. The work consists of several concrete improvements across connection inference and validation, progress visualization, editing safety, script-environment visibility, and schema-driven node configuration. These changes involved both the TypeScript/React frontend and the Rust backend.

By the end of the program, the project had produced eight merged pull requests directly related to these goals. A ninth project pull request, #219, is open for review and contains the final in-progress UI refinements.

Work completed

1. More intuitive connection authoring and validation

PR #182 introduced clearer compatible and incompatible handle feedback while dragging connections. It also made empty-space drops useful: instead of simply cancelling a connection, the editor can open a filtered list of compatible next operations. This reduced trial and error and made the operation catalog easier to discover in context.

PR #210 extended this work from frontend-only shape checks to workflow-aware inference. For a candidate connection, the frontend creates an in-memory version of the proposed diagram and asks the Rust backend to infer compatibility for the focused ports. The result can be compatible, incompatible, unknown, or provisionally compatible when more graph context is required.

The compatibility inference rejects connections that are known to be invalid, without blocking users from constructing incomplete workflows whose types cannot yet be fully inferred.

2. Clearer runtime feedback and execution controls

PR #194 added a frontend progress visualization. While a workflow is running, the editor highlights the active operation and retains visited operations so the execution path is visible on the graph. I also moved the Run and Debug controls into a persistent side-panel tab, preventing runtime status from covering the canvas. The implementation connected the existing backend WebSocket to the frontend API client, added handling for operation-started and finish events, and included a delayed calculator workflow so the visualization could be demonstrated clearly.

PR #209 renamed the underlying debug channel to interaction as the channel had grown beyond debugging into a general path for execution status and future workflow interaction.

3. Safer editing and recovery from interruptions

PR #212 prevents the Escape key from closing an editor surface while the user is actively editing text or code.

PR #216 added tab-scoped draft recovery and a New Diagram button. The editor now autosaves the main graph, active template graph, diagram properties, templates, source extensions, filename, and unfinished editor buffers. After a refresh, the user can restore or discard the saved draft. Drafts are stored per browser tab so separate editing sessions do not overwrite each other. It also added a New Diagram action and confirmation before replacing dirty work. Together, these changes make refreshing, restarting, and resetting the editor much safer.

4. Better discoverability for environments and node configuration

PR #213 added a read-only script environment panel beside the Python script form. Users can inspect the selected environment’s name, builder, language, interpreter version, configuration, and environment script without leaving the editing flow.

PR #217 replaced the free-form JSON configuration box for nodes with a form generated from each builder’s configuration schema. The form supports text and number inputs, optional values, dropdowns, checkboxes, and nested groups. Builder descriptions are displayed where the user selects a builder, and configuration examples can be previewed and applied with one click. The generated form also maintains the configuration’s required shape. This lets users configure nodes without reading Rust source code or manually constructing JSON.

Current work: fork and streaming UX redesign

PR #219 is open for review. It currently:

  • combines Fork Clone, Fork Result, and Split into one Fork operation with a behavior selector;
  • keeps node-editing popovers inside the canvas without covering the selected node; and
  • represents streaming handles as hollow amber ports that pulse when messages pass through them.

Because this pull request may continue to change after GSoC, the final GSoC snapshot is commit 5a3c9bf, dated August 17, 2026.

Pull request summary

PR Contribution Upstream status
#182 Connection compatibility hints and compatible next-operation suggestions Merged into main on April 2
#194 Frontend runtime progress visualization and persistent Run/Debug UI Merged into main on June 16
#209 Renamed the debug channel to the more general interaction channel Merged into main on June 17
#210 Inference-backed compatibility checks and explanations Merged into main on July 10
#212 Prevented Escape from accidentally discarding active edits Merged into main on July 15
#213 Script environment visibility panel Merged into main on August 4
#216 Draft recovery and New Diagram workflow Merged into main on August 10
#217 Schema-driven node configuration form Merged into main on August 17
#219 Fork operation, popover, and streaming-feedback redesign Open for review; GSoC snapshot at 5a3c9bf

Current state and next steps

The main goals of the project are implemented upstream. Connection authoring now provides immediate and workflow-aware feedback; runtime execution is visible on the canvas; interrupted edits can be recovered; destructive editor actions are safer; and node and script configuration is easier to discover and understand.

The remaining GSoC-related task is to complete review and integration of PR #219. Beyond that pull request, the validation and interaction APIs created during this project provide a foundation for future execution-time inspection and interaction tools.

Collaboration and what I learned

The project proceeded smoothly without a major technical blocker. A large reason for that was the close collaboration with my mentors: we discussed which features would be most valuable, agreed on implementation direction before committing to larger changes, and iterated through review feedback as the work developed.

My most important learning was how feature development works inside an open-source organization. I gained practical experience turning feature requests and issues into pull requests, communicating design decisions with maintainers, and adapting code to the style, conventions, and longer-term direction of both the repository and the wider organization. I also learned that successful open-source work is not only about coding. It is about making the change understandable, reviewable and consistent with the project that will maintain it. It is about the community, because it is the community that makes things happen.

Acknowledgements

A lot of thanks to my mentors, Michael Grey and Aaron Chong, for their guidance, thoughtful reviews, and frequent design discussions. I am also grateful to the Open Robotics and Open-RMF communities for the opportunity to contribute to Crossflow through Google Summer of Code 2026.

Useful links

2 Likes