Skip to content

Stage 5: pick the shell (Tauri v2 vs Avalonia), on measurements #18

Closed

Description

@Pixnop

Once the domain extraction is done the shell is an adapter, and the Electron question can be answered with numbers instead of opinions. Electron 43 today: roughly 150 to 200 MB installed, a full Chromium per app, four Node workers plus a bundled 7-Zip binary per platform.

The two serious candidates:

  • Tauri v2 keeps the React renderer, replaces Node and Chromium with the system webview and a Rust backend. Around 10 to 15 MB installed, memory divided by three or four. Cost: rewriting the ~2 900 lines of src/ipc + src/main in Rust, and a team learning Rust.
  • Avalonia (C#/.NET) puts the launcher in the same language as the game and its mods, native UI, very testable headless. Cost: the ~7 900 lines of renderer are redone.

Before deciding, measure on a one-screen prototype of each: installed size, idle memory, cold start, and the real porting cost. The stages 1 to 4 work carries over intact either way. This is a team decision.

Activity

  1. added
    roadmapPlanned refactoring stage
    team decisionNeeds a call from the team, not a lone contributor
    on Aug 16, 2026
  2. Pixnop commented on Aug 16, 2026

    @Pixnop
    ContributorAuthor

    New measurement relevant to this decision, from PR #68: the fork's unpacked Linux build dropped from 432 MB to 337 MB (app.asar 110 MB to 16 MB) just by stopping renderer-only packages from shipping twice. Electron's floor remains what Chromium costs, but option A's install-size column improves materially; the decision dossier in preparation will carry the corrected numbers.

  3. added 2 commits that reference this issue on Aug 16, 2026
  4. Pixnop commented on Aug 16, 2026

    @Pixnop
    ContributorAuthor

    The decision dossier is in: docs/decisions/0001-shell-and-codebase.md (PR #69, merged into dev; merged on locally verified gates since Actions minutes are exhausted). It reframes this issue in two ways worth reading before anything else.

    First, a third option is now on the table alongside staying on Electron (A) and porting the shell to Tauri (B): adopting Prospect, Pixnop's finished C#/Avalonia launcher for the same game, renamed (C). Everything is measured, not estimated: 337 MB installed and ~985 MiB dev-mode RSS for the fork against 109 MB and 290 MiB for Prospect; 458 tests at 47% floors against 2582 at 87% Core coverage; and honest migration costs for C (23 to 35 person-days, itemized: the i18n mechanism carries only 2 locales against our 14, self-update does not exist in Prospect at all, backups need repacking; a VS Launcher data importer already exists and works). Tauri remains the only unmeasured option; its honest first step is still the one-screen prototype this issue asked for.

    Second, a correction to this issue's own framing: the bus-factor argument does not hold as stated. Since February, 121 of the fork's 154 commits come from one person. The real A-versus-C difference on that axis is the language barrier, not headcount, and the dossier says so plainly.

    No recommendation is included on purpose. Deciders: Zaldaryon, Pixnop.

  5. Zaldaryon commented on Aug 17, 2026

    @Zaldaryon
    Collaborator

    My vote is Avalonia, and not through option C. I want the fork rewritten in C# and Avalonia rather than Prospect adopted as the base. Call it D, since the record only has three options.

    Why Avalonia wins the shell question. Weight: Prospect measures 109 MB installed and 290 MiB idle in one process against the fork's 337 MB and a 985 MiB process-tree sum, and Tauri is the one option in the record with no number beside it. A measured Avalonia app beats an estimated Tauri one that no prototype has produced. Stability: Avalonia ships its own Skia renderer inside a self-contained build, so CI tests the UI every user gets, while Tauri hands the renderer to whatever WebKitGTK a distro shipped, which for a launcher aimed at every Linux desktop is a support surface that grows without us. .NET 10 has an LTS window. Development: the game is C#, its mods are C#, VintagestoryAPI.dll is C#, and the two other repositories I work in weekly, Stratum and Nimbus, are C# on .NET 10. Tauri wins the raw community count by a wide margin, 110,292 stars against Avalonia's 31,335 and around 446 contributors against 342, and it still loses the community that answers questions about what this program has to understand. Rust would also put pathPolicy.ts and archiveValidation.ts, the security core, in the hands of people who have shipped none of it. That is the wrong place to learn a language.

    Why not adopt Prospect, despite better numbers. One reason is not a preference: Prospect is GPL-3.0 and RiftLauncher is MIT, carrying XurxoMF's copyright from upstream. Adopting Prospect as the base relicenses the product under copyleft and leaves the MIT lineage behind, and that is a decision nobody has put on the table, since the record does not mention licensing at all. It also rules out the cheaper middle path of lifting individual modules, so I am not asking for that either.

    The rest is ownership. Adoption puts the codebase, its 90 KB of French architecture.md, its personal NuGet dependency for the conformance tier, and its single-contributor history at the center of a product two people are supposed to maintain. It drops the 14 locales to 2, with the mechanism sitting in 264 abstract C# members rather than a file a translator can edit. It drops self-update to nothing on day one. And backups need repacking rather than copying, which is the one migration step that loses somebody's world when it goes wrong. Prospect is the better program today on measurements and I would rather rebuild what it does than inherit it.

    What D costs: more than either option in the record. Today's tree is about 20,300 lines of production TypeScript, 5,559 of it portable domain, plus 19,472 lines of tests. My estimate is 60 to 100 person-days for feature parity with one developer fluent in both stacks, against 23 to 35 for C and 30 to 50 for B. That number carries the same confidence as the record's own Tauri estimate, which is to say little, and the way to firm it up is the same one the issue asked for: a timeboxed one-screen spike, the versions list plus a port of the symlink rejection in assertNoSymlinkComponents, measured for installed size, idle memory and cold start.

    What D buys. MIT stays. The 14 locales stay, and the JSON surface a translator can edit stays with them. Self-update gets ported instead of lost. The security core gets rewritten by the people who wrote it. The tests become the specification for the rewrite rather than something to redo. And moving to one process retires 38 IPC channels and 108 window.api.* call sites rather than re-expressing them.

    If we cannot spend those days, the answer is A and this issue stays open, since A is the only option that ships tomorrow. What I do not think survives the record is B.

    Your vote next.

  6. Zaldaryon commented on Aug 19, 2026

    @Zaldaryon
    Collaborator

    For visibility: I pushed a local Avalonia spike to the feat/linked-game-versions branch by accident (2 GB of publish output). It has been stripped and the branch force-pushed clean.

    The spike was a rendering-model test against our layout requirements, not a decision. This issue is still the place where the shell choice lives, and it stays open for whoever wants to bring measurements.

  7. Pixnop commented on Sep 13, 2026

    @Pixnop
    ContributorAuthor

    Spike done. The host is rewritten on Tauri v2 in a separate repository, front end untouched.

    Repository: https://github.com/StratumServer/RiftLauncher-Tauri
    PR: StratumServer/RiftLauncher-Tauri#1
    Note, with the full method, tables and caveats: https://github.com/StratumServer/RiftLauncher-Tauri/blob/feat/tauri-skeleton/docs/notes/tauri-spike.md

    Both sides are 1.7.0-beta.10 of the same front end. Five cold runs each on a 9900X, WebKitGTK 2.52.6.

    Tauri skeleton Electron beta.10
    Home interactive, median 235 ms 1164 ms
    Idle memory, PSS 345 MB 408 MB
    Idle memory, RSS sum 638 MB 808 MB
    AppImage 96.0 MiB 120.1 MiB
    deb 3.5 MiB 95.4 MiB
    Installed, unpacked 278 MiB 281.5 MiB

    Startup is the clear win, five times faster, and most of it is host boot rather than the web engine. Memory is 15 percent on PSS, not the order of magnitude the framework is famous for. Installed size is a wash: the AppImage carries the whole WebKitGTK stack, 94 MB for libwebkit2gtk alone. Only the deb and rpm are small, and they are small because they depend on the system WebKitGTK instead of shipping one.

    Compatibility, the thing the spike existed to test, is clean. All seven CSS features the front relies on work on WebKitGTK, the accent ramp computes to identical values on both engines, and three routes render with zero console errors.

    Not measured, and it matters: the app has only run under the spike harness, the two sides used different offscreen displays (the asymmetry runs against Tauri), 46 of the 51 window.api members are stubs that refuse, the updater has not been looked at, and there is no pacman target or Windows bundle yet. The note lists all of it.

  8. Pixnop commented on Sep 13, 2026

    @Pixnop
    ContributorAuthor

    We stay on Electron.

    The Tauri spike (StratumServer/RiftLauncher-Tauri#1, note docs/notes/tauri-spike.md) gave us numbers. The front ports as is and WebKitGTK is clean. Startup is the one large win, 235 ms to an interactive Home against 1164 ms, and that gap is mostly the Electron host's own boot. Memory gains are small, 15 percent PSS against a skeleton, and the size argument does not hold unpacked on Linux.

    Against that: about 3000 lines of host code left to port, no drop-in for the keychain store or the updater's beta channel, no pacman target, Windows not started. It does not pay.

    The startup work continues on Electron in #456. The Tauri repository stays as a reference.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    roadmapPlanned refactoring stageteam decisionNeeds a call from the team, not a lone contributor

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions