Strand PWAs Part 2

Since my initial post was a bit scatterbrained and ill-explained, I thought before getting into any progress details I’d first re-introduce this project with a proper explainer, cover the work done, answer some technical questions, and touch on where it’s going.

What is Strand

Strand is “Progressive Web Application” (or PWA) runtime. Its primary purpose is to run web-based applications with better system integration than the browser, using only configuration – no programming. I understand my previous post used muddled language, so I’ll be using the “Runtime” term moving forward.

Strand is built using Qt/KDE tech. It uses QtWebEngine for the browser-driven work. It is using plain Qt Widgets for the interface. Initially the plan was one-main-process-per-app, but that’s changing. More on that in a bit.

The first version used AI to develop a proof-of-concept. Initially I thought I’d simply fix-up the AI codebase, but the deeper I dug the more disappointed I was. I still consider it nice-to-have, and I might occasionally pull the odd fragment from it, but the overall structure was, ultimately, unsalvageable.

Work Done & The Work-Week Refactor

Hacking on this in the evenings, I initially began by moving common functions into utility classes, general refactoring, inspecting the code more thoroughly for flaws, establishing tractable logic flows, deduplicating code, I added a couple features, etc.

It isn’t my preferred way to work, and honestly, it felt like some old jobs I used to have where most of my effort was cleaning up other people’s messes. I don’t know too many people who like working that way. Generally the way I *like* to work is by writing the code I want to write with my ideal imaginary classes, then I go and implement those classes. This was the opposite; I was grinding against classes filled with whatever was most convenient for the AI to write, and more than a few times I would find the same functionality written different ways in different places because the AI had no planning foresight.

So instead of fighting the bad code I eventually just opened a fresh project. I copied a few of the cleaned-up files, I pulled in what was working, and now I’m developing more traditionally – only I have some code reference I can pull from. I’m not saying I don’t use AI – it’s still decent at filling out the odd small method or autocompleting lines – but it was worse than anticipated at larger efforts.

How is Memory

In my initial post I mentioned Electron a few times as a heavy maintenance burden, and found a few comments wondering about memory usage. The truth is, while Electron apps are heavy, most of that weight comes simply from running the Chromium engine. My larger concern was mainly the effort involved in maintenance. While the human-written version will be different, I did some memory tests just to see where in the ballpark this might land.

My basic setup was installing a few app wrappers: YouTube Music, Flathub, and Prospect Mail (Outlook). Hilariously, one was a Snap, one was a Flatpak, and one was an AppImage. I installed all apps on Chrome (except Flathub, which has no PWA – it ran as a tab). Finally, a FlatHub profile was added to Strand.

Flathub, running as a Strand app. Took <5 minutes to prep!

The bullet-point info:

  • Running one App: Electron and Strand beat Chrome with near-identical memory usage. Chrome overhead for one app (even if only a single PWA window) can easily add 200MiB of RAM.
  • Running Multiple Apps: Chrome pulls ahead the more apps you run because it recycles the engine. The current version of Strand, as well as Electron, duplicate the engine each app. 2 apps in either Strand or Electron use more memory than Chrome. 3+ just increases the lead for Chrome.

In the revised version of Strand I’ll be using Chrome-style profiles instead of one-process-per-app. This *should* put running Strand at less memory than full-fat Chrome while offering the cumulative savings. That running PWAs in a browser you’re already using will always be most memory-efficient.

Why did I make the process structure blunder? Well, I’ll be real, the AI gaslit me. There was a bug in the early code causing profiles to share data, but the AI confidently told me I required –user-data-dir as an environment flag. It didn’t. Despite the grating discovery I’m keeping the process-level separation code. The plan now is to split the process if an app is toggling engine-level features like hardware acceleration. I’ll have a little map of the engine parameters, I’ll turn them into a little “process hash-key”, and it’ll share the engine with matching profiles.

Checking Out Youtube Music Desktop & Where it’s Going

In testing the Electron variants I found “Youtube Music Desktop”, which is probably the nicest Electron wrapper app I’ve seen. It provides a client-side decoration, very nice settings menu, and customization options which a configuration-only system like Strand simply can’t provide.

I thought about it, and questioned if Strand application profiles should include Javascript/CSS integrations as a feature so profiles can have extra enhancements… But I really didn’t like the malicious potential – especially since distribution is still a wild-card. I wondered “Could I trust a banking PWA in this system, with access knowing it’s my bank, without either verification or inspecting someones code?”

There’s also the question, “What happens if an app updates, and the custom code breaks? Will it fail to open? Will it subtly break? How long might a user have to wait before an author hears their app isn’t working?”

Ultimately I decided that I’ll integrate some ideas it offers (E.g. “Launch on Startup” as an option) but keep the overall system configuration-based. If you want to run your bank on the Strand Runtime, or a corporate-approved app, it needs to be secure and functional first. And, well, Strand was always meant to be a middle-ground; if it can’t do everything a bespoke app can do – that’s fine.

Hopefully this re-introduction was a bit clearer, and explained some of the technicalities. I’ll be posting more as the human-led version reaches parity, but this is an evening-and-weekend project so I won’t promise annoying updates until it gets interesting again.