How to make a desktop app out of a website
The question sounds like one job and is actually four. Wrapping a site so it stops living in a tab, packaging a product so customers can download it, giving a team an internal tool with its own icon, and shipping something offline capable are separate problems with separate answers. They share a search term, which is why the results are a mix of one minute menu instructions and multi day toolchain tutorials. The fastest way through is to decide which of the four is on the table before opening any tool, because three of the routes below are wrong for any given case and one is obvious once the question is stated properly.
Say which job this is before choosing a tool
Three questions settle it.
Who runs the app? If the answer is one person on one Mac, the entire signing and distribution half of the problem disappears. If the answer is colleagues or customers, that half is most of the work and it recurs with every release.
Does the app need to do anything the browser cannot? Reading arbitrary files, talking to local hardware, running when the network is down, registering a custom URL scheme. If none of these appear on the list, no code needs to be written, because a packaged browser window already does everything required.
Is the site under the same ownership as the app? Wrapping a site somebody else operates means the contents can change without notice. Wrapping a site under the same control means the page and the shell can be changed together, which makes deeper integration reasonable.
A large share of searches for this end at the first question with the answer being one person, and at the second with the answer being no. That combination has a route that takes about a minute, and reading further than that is a way of spending an afternoon to arrive at the same place.
Route one: install the page from the browser
Both browsers on a typical Mac can do this without any extra software.
Chrome takes the current page and produces a bundle through the three dot menu, then Cast, save, and share, then Install page as app. The result opens in a window with no tab strip, gets a Dock icon and its own entry in the application switcher, and is filed in a Chrome Apps folder inside the user's own Applications folder. The site does not need a manifest or a service worker; manual installation of any page has been allowed since the behaviour split out of the older Create shortcut item in Chrome 128.
Safari added the same capability in macOS Sonoma 14, under File then Add to Dock. Apple documents the important difference plainly.
A web app functions independently of Safari. It shares no browsing history, cookies, website data, or settings with Safari. Source: support.apple.com
That separation is the reason a Safari web app asks for a login on first launch, and it is also the reason two accounts on one service can become two Safari web apps. Chrome behaves the other way round: an installed app inherits the session of the profile that created it, so a second app in the same profile opens as the first account.
Neither route costs anything, neither needs maintaining, and both inherit the browser's security updates automatically. The limits show up in three places: extensions do not run inside a Safari web app, Chrome apps cannot separate accounts without separate profiles, and neither offers control over the engine when a site renders correctly in one browser and badly in another.
Route two: a site to app tool
A dedicated builder sits between the browser route and writing code. It produces a real application bundle, but the bundle points at a browser already installed on the machine rather than shipping an engine of its own.
The practical differences are narrow and they matter to specific cases. Each app can be given its own profile, which makes two accounts on the same service two separate icons with no profile switching. Extensions from the Chrome Web Store keep working inside the window, which matters for a password manager or a content blocker. The engine becomes a choice rather than a given, so a site that only renders correctly in one Chromium browser can be pointed at that browser specifically. Several tools also carry a preset list, so the URL, the icon, and the app name are filled in by picking a service instead of being typed and hunted for.
Pricing models differ more than features do. Some are a one time purchase, some are a monthly subscription, and the gap over three years is large enough to be the deciding factor when the app count is small. The Pricing page lays out where a free tier ends and a paid one starts, which is the number worth checking before counting how many apps are actually needed.
The trade off is dependency. The bundle relies on the browser it was built against, so a browser update can break an app built naively against a specific binary path. Tools differ in how they handle that, and it is the single most useful question to ask about any of them.
Route three: build it with Electron or Tauri
Writing the shell is genuinely easy. An Electron main process that creates a window and loads a URL is under a hundred lines, and a Tauri equivalent is shorter. Nothing about that part deserves a tutorial series.
Everything after it is where the time goes.
| Browser install | Site to app tool | Electron | Tauri | |
|---|---|---|---|---|
| Code required | None | None | Yes | Yes |
| Engine | The browser's | The chosen browser's | Bundled Chromium | System WebView |
| Bundle size | Negligible | Small | Well over 100 MB | A few MB |
| Security patches | Automatic | Follows the browser | Rebuild required | Follows the OS |
| Extensions | Chrome only | Yes on Chromium engines | No | No |
| Signing and notarizing | Not applicable | Handled by the tool | Required to distribute | Required to distribute |
| Cross platform | Mac only for Safari | Mac only for most | Yes | Yes |
Electron bundles its own copy of Chromium, which is why a minimal app is far larger than the page it displays and why security fixes require a rebuild rather than arriving on their own. The project supports the three most recent stable major versions, so a build left alone for a year is running an engine outside the support window. Tauri avoids the size problem by using the system WebView, which on a Mac means WebKit, and inherits its rendering differences along with its update cycle.
The cautionary case here is Nativefier, a generator that turned a URL into an Electron app from one command. It was archived in September 2023, and its own notice recommends the browser install route instead, on the grounds that browser installed apps are protected by the browser's self updating mechanism. Anything it produces today ships an engine frozen at that point.
The costs that only appear after the first build
The first build takes an afternoon. The costs that follow are the reason the route is wrong for most of the people who pick it.
Distribution requires an Apple Developer ID. An app handed to anyone other than the person who built it has to be signed and notarized, or macOS refuses to open it and reports an unidentified developer. That requires membership in the Apple Developer Program at 99 US dollars per year, plus a notarization step wired into every release rather than the first one only.
Notarization also requires the hardened runtime, which requires declaring entitlements for anything unusual, and a missing entitlement produces a launch crash rather than a helpful message. Macs run on two processor architectures, so a build has to target Apple silicon, Intel, or both, and testing on one hides failures on the other. Icons need an icns file assembled from several sizes rather than a single PNG.
Then there is updating. A packaged app has a version number and no way to change itself, so shipping a fix means running an update feed and having every installed copy notice it. None of this is difficult. All of it is permanent.
What to check before wrapping a site somebody else runs
Three properties of the target site decide whether any of the wrapping routes will hold up, and all three are quicker to check than to discover later.
How the site handles authentication. Sign in flows that open a separate popup window, and single sign on flows that bounce through an identity provider on another domain, both cross the boundary that a chromeless window draws. Some containers handle the round trip cleanly and some hand the whole thing to the default browser, which ends with a signed in browser tab and an app still showing a login screen. Testing this once, before setting up ten sites the same way, is five minutes well spent.
Whether the site assumes browser furniture exists. A page that relies on the back button, on opening links in new tabs, or on a bookmarklet is going to feel worse without an address bar, not better. Most modern applications are fine. Older internal tools built around multiple windows sometimes are not.
What the operators say about automated access. Wrapping a public site in a window is ordinary browsing and is not usually contentious, but terms of service occasionally speak to how a service may be accessed, and a site that is one part of a paid seat is worth checking rather than assuming.
None of these are reasons to avoid the approach. They are reasons to test one site before committing a workflow to it.
How the routes map onto the four jobs
For one person wrapping a site somebody else operates, the browser install route is correct and finished in a minute. Adding a builder on top is worth it at the point where separate accounts, extensions, or more than a handful of apps enter the picture, and the Features page is the shortest way to check whether a specific requirement is covered.
For an internal tool used by a team, the deciding factor is who maintains it. A wrapper that anyone can rebuild in a minute survives staff changes better than a signed Electron bundle whose certificate lives with one person. The Supported services list is a useful sanity check here, because an internal admin panel behaves like the ordinary cases on that list rather than like an edge case.
For a product shipped to customers, code is the answer, and the signing, notarizing, and updating machinery is part of the product rather than an inconvenience.
For anything needing offline capability, local files, or hardware, code is also the answer, because the packaged browser window has no access the browser itself does not have.
What to change first
Start by writing down who will run the app and whether it needs anything the browser cannot already do. If the answers are one person and no, install the page from the browser today and stop there. If the answers are several people, several accounts, or several sites, a dedicated builder such as Kagemusha covers that middle ground without inheriting an engine that has to be patched by hand.
Frequently asked questions
Does turning a website into a desktop app make it work offline?
Not on its own. A packaged browser window has exactly the access the browser has, so a site that requires a network connection still requires one. Offline capability comes from the site itself through a service worker, or from a coded app that bundles its assets locally, which is a different project.
How large is an Electron app compared to a browser installed one?
An Electron app bundles its own copy of Chromium, so even a minimal one runs well over 100 MB. A browser installed app or a wrapper that points at an existing browser adds almost nothing, because the engine is already on the machine and is shared with the browser.
Can an app built this way be given to a colleague?
Only if it is signed with an Apple Developer ID and notarized by Apple, otherwise macOS blocks it as coming from an unidentified developer. That requires Apple Developer Program membership at 99 US dollars per year and a notarization step on every release. Browser installed apps sidestep this because each person installs their own.
Which route keeps working when the website changes?
The browser install and wrapper routes, because they load the live site and inherit whatever the operators ship. A coded app that bundles a copy of the front end has to be rebuilt and redistributed when the site changes, which turns a website update into a release.