Making Web Apps into Mac Apps

November 12, 2020
Dog hiding among stuffed animals

Once I got window management under control, I also wanted shortcuts to quickly open and focus my key apps. I chose the rightmost ⌥ key + [1-9] for each app. This pattern mimics the ⌘ + [1-9] tab focus shortcuts in Safari and Chrome and felt really natural to me.

In Hammerspoon:

-- assumes you've already setup 'hyper' as a hotkey model for the right ⌥ key.
-- you can alternatively use hs.hotkey.bind without any setup.
hyper:bind({}, '1', nil, function() hs.application.launchOrFocus("Airmail") end)
-- Repeat for all your apps

Some of my key apps were web pages and thus not controllable with the above, and so I looked for ways to wrap those as native Mac apps so they would integrate more naturally.

There are several options for wrapping a native Mac app wrapper around a website:

  1. Fluid (Free, with a upgrade for some nicer features)
  2. Multi (Paids, apps generated “expire” after 2 weeks)
  3. Unite (Paid, but has a free trial)
  4. nativefier (Free, command-line)

Unite probably has the nicest generation UX, and nativefier requires basic familiarity with the command-line, but all of the options work and will generate a Mac app from a URL, and allow some level of customization1. Multi actively tries to bridge some web APIs, like notifications, to the Mac desktop equivalents as well.

I ended up using the app generated by Fluid. Multi, Unite, and nativeifer generated applications with nicer title bars than Fluid, but Fluid was free in the basic version, and added a “Open in Default Browser” in the context menu which always lets you open a link in Safari instead of in the app window itself.

The application’s behavior when clicking a link is weakest part of this whole approach. Fluid has some whitelisting options so you can choose the domains that will open in the app window versus in your default browser, but in practice this doesn’t always produce my preferred behavior - the “Open in Default Browser” menu item is a great backup.

  1. Some of the wrapping options let you specify a custom icon, but it’s something you can also do yourself easily for any app bundle. Find the bundle app for the app in Finder, hit Command-i to open the Info window, and copy and paste an image onto the icon in that window. ↩︎