Rebuilding the desktop shell on Wails

Why we are moving the CrossXCloud desktop app onto Wails, what it changes for the people using it, and what stays exactly the same.

CrossXCloud is a desktop application on purpose. Your cloud credentials stay on your machine, the canvas keeps working when your connection does not, and the window belongs to your operating system rather than to a browser tab. That decision has a consequence most people never see: something has to hold the interface and the engine together, and that seam is where a desktop app quietly becomes pleasant or annoying to use.

We are replacing that seam. The engine stays, the canvas stays, and the frame around them is being rebuilt on Wails.

What we built on

The first version of the app used a small library that pairs a Go program with the web engine your operating system already ships. No bundled browser, a modest download, and a fast cold start. That was the right call and we would make it again today.

It is also minimal by design, and after a year of living in it we were paying for the parts it left to us.

The window was the visible cost. CrossXCloud uses its own title bar rather than the platform’s, which means the app is responsible for dragging, resizing, snapping, and the thin border around the edge. Getting that to feel native on Windows took us into maintaining our own build of the window layer. It worked, but a patched foundation is a strange thing to stand on, and every fix had to be re-earned.

The other cost was invisible and more expensive. Every call from the interface to the engine was a string with some JSON attached. Nothing checked that the name existed, that the arguments matched, or that the answer had the shape the screen expected. When those drifted apart, the first indication was the running app.

Why Wails

Wails starts from the same premise: Go on the inside, your operating system’s own web engine for the interface, one binary at the end. The difference is how much of “being a desktop app” it considers its job. Frameless windows, deep links, single-instance behaviour, and native file dialogs are part of the framework rather than things each application patches in for itself.

The part we care about most is the seam. In Wails, the interface calls real Go functions with real types. If a signature changes and a screen has not caught up, the build fails. That is a much better place to find out than a support ticket.

It also gives the engine a way to speak. Previously the interface could ask questions and the engine could answer, but the engine could never volunteer anything, so anything that changed on its own had to be discovered by asking again on a timer. Now it can simply say so.

What you should notice

Not a redesign. The canvas is the canvas. What changes is a set of small things that add up:

Failures explain themselves. The engine already understood the difference between a quota you need to raise, a permission you need to grant, and a genuine outage. Until now it had no way to pass that distinction across to the screen, so a lot of different problems arrived looking identical. They no longer have to.

Your operating system’s dialogs. Where the app needs a file or a folder from you, it asks with the picker you already know instead of a text box expecting a path.

Fewer things on a timer. When the app can be told something changed, it reacts immediately rather than at the next check.

A window that behaves like a window. Resizing, snapping, and the edges of the frame become the platform’s job again, on all three operating systems.

What does not change

The engine that talks to your cloud accounts is untouched. So is the encrypted credential vault, the plan and apply flow, and everything about how the canvas works. This is not a rewrite of the product. It is a replacement of the frame around it, and if we do it well the most common reaction will be that nothing happened.

Why now

The cost of a bad seam is paid every time someone crosses it, and the number of crossings only grows. Doing this while the surface is still small is inconvenient. Doing it later, with more screens and more people relying on them, would be considerably worse.

We would rather spend the time now and stop paying interest on it.