Site shortcuts in the Dock: what it does and where it breaks down
The phrase site shortcuts in the Dock describes a single gesture that ends in three different results. One produces an application bundle that macOS treats as a program. One produces a document that opens a browser tab. One produces nothing at all and disappears when the browser quits. Instructions written for one of them look like they work for the others right up until the moment something has to behave a certain way, and then the difference matters. Deciding which of the three is actually wanted is the whole of the problem.
Three results, one gesture
A Dock is one strip, but it is divided by a separator, and the two halves hold different classes of object. Applications go on the left. Folders, documents, and the Trash go on the right. Nothing changes that, which means the class of the thing being created decides which half it can occupy.
An application bundle lands on the left. It appears in Command Tab, gets its own entry in Spotlight, counts as a separate window in Mission Control, and can take a full screen space of its own. A URL document lands on the right, next to folders, and clicking it hands the address to the default browser, which opens a tab. A running browser window shows an icon only while it runs, and the icon goes away when the process quits.
Most of the confusion that shows up afterwards traces back to this split. An icon that refuses to sit next to the other apps is a document. An icon that vanished overnight was never kept in the first place. Neither is a malfunction.
What changes once it is a real app
Turning a site into a bundle changes how macOS accounts for it, and that accounting is the actual benefit. Notification settings list it by name, so banners and sounds can be tuned for that one service instead of for the entire browser. Focus modes can exempt it individually. A badge on the Dock icon can show an unread count that would otherwise be buried behind whichever tab happens to be frontmost. Login items can open it at sign in.
When the app is built with Safari's own feature, Apple states the isolation 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 isolation is the feature and the friction at once. Two accounts on the same service can run side by side without a private window, which is exactly what people with a work Google account and a personal one are after. The same property means the first launch asks for a password and a second factor, because none of the browser's existing sessions carry over.
The engine underneath is still a browser
A standalone window does not make the site into native software. The page is still rendered by a browser engine, so any limit that belongs to the site belongs to the app. Offline behavior depends on what the site implemented. Keyboard shortcuts are whatever the site defines. File uploads and downloads work the way the site makes them work.
Extensions are where the choice of engine shows up most. A Safari web app carries a toolbar with buttons for installed Safari extensions. A Chromium based build runs Chrome extensions, which matters to anyone whose daily workflow assumes a password manager or a content blocker is present. The engine is decided at creation time and is expensive to change afterwards, so it belongs in the first decision rather than the fifth.
Where it breaks down: sessions
The most common stall happens within the first two minutes. A build that separates cookies starts signed out. If the second factor lives on a phone that is in another room, the project stops there.
Single sign on adds a second version of the same problem. Some identity providers complete authentication in a secondary window. Whether that window is allowed to open depends on how the app handles links, and an app configured to send everything outward will push the authentication step into the default browser, where it completes and then has nowhere to return to. The loop looks like a failure of the app and is really a mismatch between the link policy and the login flow.
Where it breaks down: link direction
Every standalone app has to answer one question that a browser tab never asks. When a link is clicked, does the page open here or somewhere else.
For a chat service, the answer is almost always somewhere else, because the window fills with unrelated sites otherwise. For an internal admin panel, the answer is almost always here, because the navigation is internal and sending each click to the browser defeats the point. Getting this backwards produces a small irritation many times a day rather than one visible failure, which is why it often goes unexamined for months.
Traffic arriving from outside deserves the same attention. A link in a mail client opens in the default browser. Having it land in the app instead requires the tool to register for that address, and not every approach can.
Where it breaks down: ownership of updates, names, and icons
An app built from a browser depends on that browser. When the browser ships a major update, wrapper style builds have been known to stop launching, and whether that is recoverable depends on how the bundle references the engine. Knowing which route was used is what makes that morning a five minute problem instead of an afternoon.
Appearance has an owner too. Builds that pull the site's favicon inherit whatever the site decides to ship, so a rebrand changes the Dock. Builds that let the name, the URL, and the icon be set at creation keep that control on the local machine. Safari web apps expose all three in a settings panel after the fact, which is worth knowing before spending time on a custom icon.
Removal differs by route as well. One route wants the bundle dragged out of the Applications folder inside the home directory. Another offers an uninstall command from inside the app itself, with a checkbox for the stored site data. A third manages everything from a list. Mixing routes over time leaves leftovers that nobody remembers creating.
Where it breaks down: notifications need two permissions
A badge requires two separate grants, and a missing one produces silence rather than an error. The site has to support web push, and macOS has to permit notifications for that app. The site level prompt usually appears once, shortly after first load, and dismissing it means going back through system settings later.
The upside of clearing both is control that tabs cannot offer. Sound off, banners off, badge on produces a service that reports its count without interrupting anything, and that combination is only addressable because the app exists as a separate entry in the notification list.
The three results side by side
Descriptions blur together. Behavior does not.
| Application bundle | URL document | Bookmark | |
|---|---|---|---|
| Side of the Dock | Left of the separator | Right of the separator | Not in the Dock |
| Result of a click | Standalone window | Browser tab | Browser tab |
| Command Tab | Listed separately | Not listed | Not listed |
| Unread badge | Possible | No | No |
| Session | Can be isolated | Shared with browser | Shared with browser |
| Where it lives | Applications folder | Anywhere on disk | Inside the browser |
Anyone whose goal is a shorter tab strip is looking at the first column only. The other two end in a tab, which adds one back the moment they are used. That single row explains most cases where a set of instructions was followed correctly and the result still felt wrong.
The first column carries maintenance in return. A bundle is a file, so it has a name to choose, an icon to set, and a removal step when it stops being useful. At two or three apps that cost is invisible. Past a dozen, the question of which app was built with which browser becomes real, and an approach that keeps a single list of everything starts to pay for itself.
What this is not
Two adjacent ideas get mixed in and are worth separating. A progressive web app is something a site publishes; whether a site can be installed that way is the site's decision, not the reader's. A wrapper built on a local browser engine works on any address, including internal tools that were never designed for installation, which is why the two approaches cover different ground even though the resulting window looks identical.
The second idea is the native rewrite. Some services publish a real desktop client, compiled and shipped by the vendor. Where one exists and is maintained, it usually wins on integration depth. Where it does not, or where the published client lags the web version, a standalone window over the web version is the closer substitute. Checking whether a first party client exists takes one search and removes the question entirely.
Deciding what deserves a slot
Moving every open tab into the Dock recreates the original problem in a new place. Four questions narrow it quickly. How many times a day does it get opened. Does it stay open for long stretches. Is it used under more than one account. Is a notification count useful. Services that answer yes to two or more are worth a slot, and that filter usually lands between five and ten icons.
Sites reached through search rarely qualify, because the search happens anyway. Internal tools with long unmemorable addresses almost always do, because the address is the reason they are hard to reach.
The services that fail the filter are worth recording somewhere, along with the reason. Six months later the same candidates come up again, and a one line note prevents a second round of the same deliberation. The list also tends to reveal a pattern: the tools that keep failing the filter are usually the ones that should be consolidated or dropped rather than made easier to open.
What to change first
Pick the single service opened most often yesterday, decide which account it runs under, and build one app with that account before touching anything else. If the standalone build satisfies the extension requirement, the multiple account requirement, and the management requirement, the work is done and it cost nothing. If one of those three is missing, that gap is the specification for a dedicated tool, and a build with a large preset library gets a second and third app made in under a minute each. Compare the Supported services list against yesterday's history, and check what the creation screen actually exposes in Features, since the link policy and the session behavior are set there rather than discovered later. The full creation flow for the route that keeps browser extensions intact is documented in the Kagemusha guide.
Frequently asked questions
Does putting a site in the Dock keep me signed in?
It depends on the route. A Safari web app shares no cookies or browsing data with Safari, so the first launch requires signing in again, including any second factor. A build that reuses an existing browser profile arrives already signed in. The separated version is the one to pick when two accounts on the same service need to run at the same time.
Why does the icon sit on the wrong side of the Dock?
Because the object created was a document, not an application. The separator divides the Dock into an application area and a folder and document area, and a URL file is a document. Creating an actual application bundle, through Safari's Add to Dock or Chrome's Install page as app, places it on the application side.
Do browser extensions still work in a standalone app?
Only the ones belonging to the engine used to build it. A Safari web app shows buttons for installed Safari extensions in its toolbar. A Chromium based build runs Chrome extensions. Since the engine is fixed at creation time, a password manager or content blocker that is part of the daily routine should decide the route before the app is made.
Why is there no unread badge on the Dock icon?
Two permissions are required and both must be present. The site has to support web push, and the app has to be allowed to send notifications in macOS system settings. The site's own permission prompt tends to appear once, right after the first load, so a dismissal there has to be reversed from the notification list in system settings.