Make a website behave like a desktop app

The phrase "convert a web application to a desktop application" covers two jobs that look identical and cost completely different amounts. One is making a site that is already used every day open in a dedicated window instead of a tab. The other is packaging a product so other people can download and install it. The first takes about a minute. The second takes a build pipeline, a signing certificate, and an update channel that has to keep working for years.

Deciding which job is actually in front of the reader is the whole decision. Most searches land here wanting the first and start reading about the second.

Which of the two problems is being solved

The tell is who installs it. If the answer is "one person, on their own Mac, so a service stops living in a tab", nothing needs to be built. macOS and the major browsers already ship the feature, and it costs nothing to reverse.

If the answer is "customers", the job is software distribution. That means a wrapper project, a repeatable build, a code signing identity, notarization so Gatekeeper allows the app to open, and a mechanism for shipping the next version. None of that is exotic, but none of it is a one minute change either, and the requirement to maintain it never ends.

There is a third case worth naming because it is common and gets misfiled as the second. A small team wants the same set of internal tools to open the same way on everyone's machine. That looks like distribution, but the audience is known and trusted, so the honest answer is usually a documented setup step rather than a packaged application.

The route with no build step

Both mainstream browsers on macOS can turn a page into a standalone window with its own icon.

Chrome does this through the three dot menu, then Cast, save, and share, then Install page as app. Safari does it from the File menu with Add to Dock, which has been available since macOS Sonoma 14.

A web app is an app built for the web that you can access on any device. You can use web apps to have a website work as an app and access it on your computer or mobile devices through the launcher or home screen. Source: support.google.com

What arrives is a real window with no tab strip and no address bar, an entry in the application switcher, and a Dock icon that can carry a notification badge if the site supports it. Chrome ties the result to the profile that installed it, which is how two accounts on the same service end up as two separate icons. Safari gives the window its own cookie store that is not shared with the browser at all.

What does not arrive is any capability the site did not already have. Offline behaviour depends entirely on whether the site ships a service worker. File system access, global keyboard shortcuts, and menu bar items are not added by the window. The window changes where the site lives, not what it can do.

For an individual trying to stop losing a tool in a row of tabs, this is the correct answer and the article can stop here. For anything that needs to reach beyond the page, keep reading.

Wrapping it in a runtime

A wrapper is a native application whose entire user interface is a browser view pointed at the web application. Two toolkits dominate.

Electron bundles Chromium and Node.js into the application itself. Rendering is identical everywhere because the engine ships with the app, and Node gives the wrapper full access to the file system, child processes, and native menus. The price is size and memory. Each app carries its own browser, so downloads run into hundreds of megabytes and every running instance is effectively a separate browser.

Tauri takes the opposite trade. It uses the operating system's own web view, which is WKWebView on macOS, and keeps the native layer in Rust. Bundles are dramatically smaller, but rendering now varies with the version of the system web view on each machine, so testing has to cover the platforms separately.

Installed web app Electron wrapper Tauri wrapper
Build pipeline needed No Yes Yes
Ships its own engine No Yes No, uses the system web view
Native menus, tray, global shortcuts No Yes Yes
Rendering consistent across machines Follows the browser Yes Varies with the system web view
Signing and notarization to distribute Not applicable Required Required
Reversible in one click Yes No No

The table understates one thing. A wrapper is not finished when it launches. It is finished when it can be updated, and the update path is where wrapper projects quietly die.

What a wrapper actually buys

The reason to accept the cost is access to the operating system. A page in a window cannot do these things. A wrapped application can.

Presence outside the window

A menu bar item, a tray icon with a count, a badge that survives the window being closed, and a global keyboard shortcut that brings the app forward from anywhere. For a tool that needs to be summoned rather than visited, this is the difference that matters.

Files and protocols

Reading and writing local files without a download folder round trip, registering a custom URL scheme so links elsewhere open the app on the right screen, and accepting drag and drop from Finder into the interface.

Behaviour when closed

A background process that keeps a connection open, syncs, or notifies while no window is visible. A browser tab cannot promise this. The browser is free to discard it.

If none of these three appear on the requirement list, the wrapper is being built for appearance, and the built in install route delivers the same appearance for free.

The bills that arrive later

Distributing a macOS application outside the App Store means signing it with a Developer ID and submitting it to Apple for notarization. Without both, Gatekeeper refuses to open it on other people's machines, and the failure looks to the user like a broken download. The identity requires a paid annual membership in the Apple Developer Program, and the notarization step has to run on every build that leaves the machine.

Updates are the second bill. A web application updates when the server updates. A wrapped one does not. Something has to check a feed, download, verify a signature, and swap the bundle. Skipping it means shipping a version that is frozen at release day while the site behind it keeps changing, which produces the worst possible failure mode: an application that looks fine and silently talks to an API that has moved on.

Sessions are the third. Each wrapper keeps its own cookie storage, separate from the browser. A user signed in to the site in Chrome will be signed out inside the wrapper, and any single sign on flow that redirects through an identity provider has to complete inside that window. Flows that bounce out to the default browser will break the isolation and sometimes the login.

None of these are reasons not to wrap. They are reasons to be sure the requirement list justified it before the first line of code.

Three situations and the route each takes

Abstract trade-offs are hard to weigh, so it helps to see how the decision resolves in the cases that actually turn up.

A dashboard that has to stay open all day

A monitoring view, a support queue, or a shared inbox that is checked constantly. The requirement is a window that does not get closed by accident and an icon that shows when something arrives. Nothing here needs the file system or a background process. The installed web app route covers it, and the setup survives a browser update without anyone maintaining it.

An internal tool used by twenty colleagues

The temptation is to wrap it so everyone gets the same icon. Weigh that against the cost. A wrapper for twenty known machines still needs signing and notarization, because Gatekeeper does not care that the audience is friendly, and someone becomes responsible for the update path forever. A one page setup note showing how to install the page as an app usually delivers the same result on day one and costs nothing on day four hundred.

A product sold to customers

Here the wrapper is often correct, but the reason should be a capability rather than a look. A file sync tool needs the file system. A meeting client needs a global shortcut and a tray presence. A note taking product that wants to open at login and capture from anywhere needs both. If the feature list is genuinely inside the page, the honest version of the product is a well built site plus an install prompt, and the engineering budget goes into the site instead of the packaging.

A tool that has to talk to local software

The clearest case for a wrapper is when the application has to reach something on the machine that a browser sandbox blocks. A local database, a hardware device on a serial port, a command line tool that has to run with the user's own permissions. No amount of browser configuration gets there. If that requirement is on the list, the decision is already made and the rest of this article is about managing the cost rather than avoiding it.

When the real problem is the number of apps

There is a version of this question where neither answer fits. The reader does not need one site to become an app. They need eight sites to stop competing for one window, several of them signed in twice under different accounts.

Wrapping does not scale to that. Eight wrappers means eight runtimes, eight update paths, and eight near identical icons in the Dock. Installing eight web apps is cheaper but produces the same crowded switcher, and the account each icon belongs to becomes invisible.

The tools built for that shape keep every service in its own window inside one application, with the session boundary drawn per service rather than per browser. Open source options such as Ferdium take that approach, and whether the specific services in use are already handled is worth checking against a supported apps list before committing, because the awkward cases are always the internal dashboards rather than the well known names.

What to change first

Install the one service that is opened most as a web app today, using the browser already in use, and see whether the friction moves. If it disappears, the problem was one tab. If it just relocates to a crowded Dock, the problem was the number of accounts, and a browser that keeps each one in its own window, such as SpaceDeck, addresses that directly without a build pipeline.

Frequently asked questions

Is there a way to convert a website into a Mac app without writing code?

Yes, for personal use. Chrome's Install page as app and Safari's Add to Dock both produce a standalone window with its own icon and no build step. Command line wrappers that generate an Electron bundle from a URL also exist, but the output still needs signing and notarization before it will open on anyone else's Mac.

Will the desktop version work offline?

Only if the site already works offline. A wrapper or an installed web app loads the same pages from the same server, so offline support depends on whether the site ships a service worker and caches what it needs. Packaging does not add offline capability by itself.

Why does the wrapped app ask for a login when the browser is already signed in?

Each wrapper keeps its own cookie store, separate from Chrome, Safari, and every other wrapper. Signing in once inside the window is normal and the session persists there afterwards. The exception is a single sign on flow that redirects to the default browser to finish, which leaves the wrapper without the cookie it needed.

Does an Electron app use more memory than the same site in a tab?

Usually yes, because each Electron app runs its own copy of the browser engine instead of sharing one with every other tab. Two wrapped apps mean two engines. Tauri avoids most of that by using the system web view, at the cost of rendering differences between machines.

Back to all posts