From the browser to the desktop

Solo Composer is my research project into how music notation software works, closely modelled on Dorico. It started as a web app, and Part 1 and Part 2 of this series cover those early days: React for the interface, with a Rust engine compiled to WebAssembly doing the heavy lifting.

It's been refined a number of times in the browser since, and each version taught me more about the problem. At the end of 2024 I started the current version as a native desktop app, built with Tauri. The browser took Solo Composer a long way; going native opened up the things a web page can't do.

Keeping what worked

Tauri pairs a web front end with a Rust back end, which suited the project well. The React interface carried over, and Rust stopped being something compiled to WebAssembly and called from the page. It's now the core of the app, running natively.

The ideas carried over too. The score still stores musical events and works out the notation from them, and drawing is still kept separate from working out the layout. That separation, set up in the very first version, meant the move was a change of engine, not a change of design. A typical score now lays out in a few milliseconds, and drawing runs on the GPU.

Solo Composer's Sequence mode, with a track for each player above a piano roll

Things a browser tab can't do

The bigger change was what became possible at all:

  • Real project files. Scores are saved to disk in the app's own file format, rather than living inside the browser.
  • Proper windows. The instrument picker, preferences and settings open as their own windows.
  • Plugin instruments. The app can host VST3 instruments alongside its built-in sampler.
  • Agent access. The running app can let AI agents create and edit scores directly, which I've written about in Solo Composer: An MCP Server Inside the App.

None of these were realistic as a web page. As a desktop app, each one became a normal piece of work.

Takeaways

  • The browser versions paved the way. The score model and the split between layout and drawing carried straight over.
  • Tauri let me keep my tools. React for the interface, Rust for everything heavy, now running natively.
  • Going native raised the ceiling. Real files, native windows, plugin instruments and agent access all came within reach.