Skip to content
megapromotingLet's talk

Expertise · Desktop applications

Applications that are installed on the computer. On macOS we have built two; for Windows and Linux this page is an offer, not a history.

We build native applications for macOS, with the logic core separate from the screen, so that the same logic also works on the phone. For Windows and Linux/Ubuntu we do not have anything delivered yet and we write that as such, with the conditions under which we would accept the work. The first question remains whether you really need an installed application.

An offer, with conditionsThe rule is mechanical and I apply it mechanically. On macOS we have two in-house implementations, built and runnable: a menu bar app with 25 Swift files, which reuses 15 files from the core of an iPhone project, and a second, simpler app, which is a WebKit wrapper over a web app. Both have a compiled binary on this machine. But the service, as it is named, covers three families of systems, and for two of them — Windows and Linux/Ubuntu — we searched seriously and found zero: no in-house .NET or Qt project, no `tauri.conf.json`, no Electron written by us, no `.desktop`, no deb, rpm or AppImage packaging. In addition, neither of the two macOS apps has ever been packaged in a distributable installer. With only one of three platforms covered and zero distributions, the page is written as an offer with conditions. When we deliver the first Windows or Linux application, the value changes, not the text.

The first question we ask you is not for which system, but whether you really need an installed application. It is worth installing when it needs something the browser does not give it: direct access to sensors or peripherals, a permanent presence in the system tray, working without internet, access to files on the disk without the person loading them every time, or running in the background when the window is closed. If none of these is required, a site that opens from a link is cheaper to build, update and maintain — and we tell you that, even if the work ends up smaller.

On macOS we have two built applications. The first is a menu bar application: 25 in-house Swift files, plus 15 core files taken directly from the iPhone project of the same product — the same files, not a copy. It is built with a script that calls the Swift compiler directly, target `arm64-apple-macosx14`, linking eleven system frameworks, including SwiftUI, AppKit, CoreMotion, Vision and UserNotifications. The resulting binary is 6,516,128 bytes. The second is much simpler and it is honest to say how much: three Swift files, a WebKit wrapper over a web application, with sandbox and hardened runtime enabled, compiled universally for Intel and Apple processors. They are two different things and we call them differently.

What we do not have, stated clearly. Windows: zero. We looked for .NET, WPF, WinForms, WinUI projects, `.xaml`, `.appxmanifest`, `.msi`, `.wxs` files — everything we found on disk belongs to a third-party C library, vendored in another project, which we did not write. Linux desktop: zero — no `.desktop` file, no deb or AppImage package built here. Electron or Tauri written by us: zero. And, just as important: neither of the two macOS applications has ever been packaged into an installer. They exist as locally built `.app` packages, ad-hoc signed, without a team identifier.

What nevertheless transfers from the experience so far, and this is the part that matters for a new project: the discipline of keeping the logic core separate from the interface. In the macOS project, the calculation and policy files do not import the interface, so they compile and run on the Mac as a normal programme, without the simulator; their logic suite runs in a few seconds. The same separation means that porting to another system is a matter of wrapper, not rewriting. That is what we rely on when we say we could do Windows or Linux — not on an experience we do not have.

What it covers

The work, by component

First we decide whether you need an installed application

Five criteria, checked one by one: access to sensors or peripherals, presence in the system tray, working without internet, direct access to files on the disk, running in the background with the window closed. If none applies, the recommendation is a web application, and the reason is practical: an installed application must be signed, distributed and updated on each computer, and each of the three steps costs endlessly, not just once.

The core is written once and does not know what it runs on

In our macOS application, the desktop target lists 15 files from the core of the iPhone project as in-house sources — calculation, calibration, history, notification and health data policies. They are not copied, they are the same files. The consequence: an algorithm fix is made in one place and appears in both. The second consequence, more important for you: the core can be tested without starting the application.

The platform wrapper remains thin, and we tell you how thin

The menu bar application uses `MenuBarExtra` over an AppKit application delegate — native code, but little of it, because the rest is the common core. Our other macOS application is at the opposite extreme: three files, a `WKWebView` wrapped for SwiftUI, that is, a window over a web application. Both are legitimate macOS applications, but they mean different things in terms of effort, speed and system access. Which one you need is decided at the beginning, not discovered at delivery.

We build with a script, not with the click of a button

The menu bar app is built from a script of under a hundred lines that calls the Swift compiler directly, with the target and list of frameworks written explicitly, then lays out the `.app` bundle and signs it. A build that fits in a script runs the same on another machine and can be put into an automated line; a build that exists only in the interface of a development programme cannot.

Sandbox and hardened runtime, when the application goes on the network

The second macOS application starts with sandbox enabled and a single network permission, that of client — not server, no access to the user's files, no camera, no microphone. Hardened runtime is enabled from the project configuration. Permissions are declared from the start, as a short list that can be read, not added along the way when something does not work.

Signing is a matter of account, not code, and we put it on the table at the start

Our macOS applications are ad-hoc signed: verification passes locally, but there is no team identifier, and in the project configuration the development team field is empty. For distribution outside the store, a macOS bundle needs signing with an identifiable developer certificate and passing through Apple notarisation, otherwise the operating system of the recipient blocks it. It is a matter of account and process, not functionality — but it is a real problem and we do not hide it at the last meeting.

Windows and Linux: what we ask before we accept

A paid compatibility check as the first stage, which ends with a skeleton that starts on your computer, not with a document. In it, three things are decided: which runtime environment we use and why, who owns the signing certificate and distribution account, and how an update reaches people's computers. If any of the three has no answer, the work does not begin. We do not take on a platform we have not delivered while pretending it is a formality.

Linux server is not Linux desktop, and we do not confuse the two

Our systems run day to day on Linux: system units with restart on failure, web server in front, logs and their rotation. That is real experience with Linux, but it is server experience. A windowed application for Ubuntu is a different discipline — packaging, integration with the graphical environment, distribution through a repository or as a self-contained file — and there we have nothing delivered. An engineer can make that difference in three seconds; it is better that we say it first.

What we do not do

We do not promise an installer we have never produced without saying it is the first time. We do not choose a runtime environment just because it is fashionable, without first checking what the application needs from the system. And we do not take over an existing desktop application before we can build it from scratch, on our machine, from the received sources — if the build does not reproduce, any estimate after that is a guess.

What it looks like

The path, step by step.

01

We decide installed or web, on five criteria

Sensors and peripherals, system bar, offline work, file access, background running. We deliver the decision in writing, with the reason, even when the reason is "you do not need an installed application". This stage is short and can stop here without loss.

02

We build the core and test it without a platform

Logic, states, persistence, policies — written so the interface does not matter and it can be compiled and run as a command-line programme. We deliver the test suite and the command with which you run it. If later a second platform appears, this shows whether the work was done correctly from the start.

03

We put on the platform shell

On macOS: windows or menu bar, notifications, permissions, the `.app` bundle, the build script. On Windows or Linux: after the compatibility check from the first stage, with the runtime environment chosen there. At the end of the stage the application starts on your machine, not on ours.

04

Signing, distribution, updating

The stage that most projects discover late, and we place last explicitly so it is visible: certificate, account, notarisation where the platform requires it, update channel. This is also our current macOS blocker — the applications are signed ad-hoc, without a team identifier. In your project, the account is yours and the blocker disappears.

DocumenteConversationsSourcesSummaryActionTeamContextualiseAuthorised sources. Reviewed actions.
A core in the centre — calculation, calibration, history, policies — which imports no interface and is therefore tested on its own. Around it, four platform shells: iPhone and macOS, connected and built, drawn filled; Windows and Linux desktop, drawn open, because they do not exist. The fifth node, distribution, is linked to macOS by a dashed line: the package is built and signed ad hoc, but does not pass notarisation, so it does not reach another computer. The drawing says what is done and what is not, in the same image.

The data

What we touch, where it lives, and how long it stays

The questions anyone with a data protection officer would ask — asked here before they do.

An installed application sees more than one in the browser
That is why you want it and, at the same time, its risk: it has access to the disk, to the user’s file system and, if permissions are granted, to peripherals. That is why permissions are declared explicitly and kept to a minimum. Our sandboxed application has exactly one permission, that of a network client.
Where the data sits when the application has no server
On the person’s computer. In the menu bar application, the history is written to its own file, and the preferences to the system settings store, with keys prefixed by application. Nothing goes to a server for a simple reason: there is no network code in the application. Where there is, the permissions page states who receives what.
What we do not collect by default
No telemetry, no device identifier, no usage report, unless explicitly requested and declared in the interface. A desktop application is a place where telemetry goes unnoticed; that is why, if it is added, it is added visibly, with an off button, and it is stated which fields leave.
Updates are a decision, not a technical detail
We do not currently have a built automatic update channel. In a new project this is one of the first three decisions, along with signing and distribution: update manually, through the platform store, or through a dedicated channel? Each option has a different ongoing cost and a different security surface, and it is chosen before the first line of code, not after.
What remains with us
The source files, while we work; after handover, what was agreed in the contract. Signing certificates remain, ideally, on your organisation account — if they remain on ours, you are tied to us for every update, and that must be a conscious choice, not a consequence.

A case

A macOS application extracted from the core of an iPhone application, without a second implementation

The situation

We had our own iPhone product, which measures head tilt relative to a position calibrated at the start of the session. The same rules — calibration, thresholds, history, notification policies — made sense on the Mac as well, where the person is anyway in front of the screen. The real question was not whether it could be done, but how much logic should be rewritten.

What we built

Zero, because the core had been written from the start without knowing about the screen. The macOS target lists 15 files from the iPhone project as its own sources, to which 25 desktop-specific Swift files are added: the window, the system tray menu through an AppKit delegate, notifications, the environment service. The build does not go through the Xcode interface: a script calls the Swift compiler directly with the target `arm64-apple-macosx14` and explicitly links eleven system frameworks, then places the `.app` package and signs it, and finally verifies the signature.

What came out

A binary of 6.516.128 bytes for Apple processors, which starts and stays in the menu bar, built from a single command. The same algorithm correction reaches the phone and the Mac, because it is the same file, not a manually synchronised copy.

What the case does not say

The application is not distributed and cannot be, at present, in this form: the signature is ad-hoc, without a team identifier, and the development team field is empty in the project configuration. On another computer it would be blocked by the system. It is an account and notarisation problem, not a functionality problem — but it remains an unresolved problem and we write it as such, not as a detail.

Questions

What people ask us before they call

Why does it say “offer” on this page, if you say you have two Mac applications?

Because the service is called “desktop applications” and covers three system families, and we have delivered for one. The rule we apply to ourselves requires a minimum of two own implementations, visible in code, for every statement of the “we have done” type. On macOS we have them. On Windows and Linux we have zero, and neither of the two Mac applications was ever packaged into a distributable installer. A page that said otherwise would fail at the second question from an engineer.

Do you have a Mac application I can download now?

No. Both exist as `.app` packages built on our machine: one compiled for Apple processors, the other universal, for Intel and Apple. They are ad-hoc signed, which means they pass local verification but do not have a team identifier, so on another computer the system would block them. What we can do in front of you is start them, open the code and the build script, and run the logic suite.

What is the difference, for you, between the two Mac applications?

One is native, the other is a window over the web, and the difference is large. The native one has 25 own Swift files plus 15 core files shared with the iPhone version, hooks into the menu bar through an AppKit application delegate and links eleven system frameworks, including motion sensors, notifications and image processing. The second has three files and displays a web application in a `WKWebView`. The second is quick to build and is the right choice when your application is already web-based and you only want an icon in the Dock. It is not the right choice when you need system access.

Do you make applications for Windows?

We have not delivered any and do not claim otherwise. We searched our disks for any trace — .NET projects, WPF, WinForms, WinUI, XAML interface files, application manifests, MSI or WiX packages — and everything that appears belongs to a third-party C library that we only use in another project. If you need Windows, the first stage is a compatibility check that ends with a skeleton that starts on your computer, and only after that do we discuss the rest.

But for Linux or Ubuntu?

The same position, with an important clarification. Windows desktop application: zero delivered, no deb or AppImage package built by us. Linux servers: day by day — systemd units, web server in front, logs, restart on failure. These are two different disciplines and it would be dishonest to use the first as proof for the second.

Why not Electron, if that is simpler?

Because we have not delivered any and we are not going to pretend that we have experience where we do not. On our disks there are two functional Electron applications, but they are repositories cloned from other authors, with zero contributions of our own — we checked them in the commit history precisely so they would not end up as “proof” on this page. In a real project, the choice between a packaged web environment and native code is made after it is known what the application needs from the system, how much the package weighs and who pays for maintenance, not by fashion.

What blocks, for you, the publication of a Mac application?

The account, not the code. In the project configuration, the development team field is empty, and the signature of the built package is ad-hoc, without a team identifier. For distribution outside the store, macOS requires an identifiable developer certificate and the package to pass notarisation. In your project, the certificate and account belong to your organisation, so this block simply does not appear — but it must be planned from the start, with its cost and time.

Isn't it simpler to make a website and finish?

Often yes, and we tell you that before you tell us. A website does not need signing, notarisation, an installer, an update channel or a version for each operating system. The installed application wins when you need sensors, peripherals, offline work, permanent presence in the system tray or direct access to the user's files. If none of these is on the list, the money is better spent elsewhere.

Can you take over a desktop application we already have?

With one condition checked before any estimate: we must be able to build it from scratch, on our machine, from the sources received. If the build does not reproduce — dependencies, certificates, unwritten steps are missing — then nobody can honestly estimate anything, and the first task becomes reproducing the build, not the new functionality. We say this in advance, so it is not discovered halfway through.

What the statements above rest on (14 sources)

14 of them are code and files from our repositories. We don't publish their name or line: together, on a single page, they would describe too precisely how systems that aren't only ours are built. We go through them with you, in the repository, on request — verification stays possible, it just happens in a conversation.

What would you want to work better?

Tell us about your process. Together we decide what is worth building, what we can connect, and how we check the result.

Let's talk