Multi

Last week I joined a programming community on Discord.
I’m now a member of three programming community chats on Slack, one on Zulip, and this new one on Discord.
These are all social groups (as opposed to professional), so I don’t need them open all the time.
I just like to keep up with the conversations and contribute where I can.
Having to do this across three different apps is annoying—I want one app to open/close; one app in my ⌘-Tab switcher; and one app displaying notifications.
That annoyance led to Multi.

Multi lets you create a custom, lightweight macOS app from a group of websites.
Each website is loaded in native WebView with a small JS shim to bridge web notifications to the macOS Notification Center.
I originally prototyped with Serge Zaitsev’s webview library, but later realized that using WebKit directly would save me some time and indirection.
This project was built over the course of one week, so there are definitely some rough edges, but it’s fun that it works as well as it does.

I built Multi without XCode, which proved to be the most challenging part.
At first, I did this because I didn’t have XCode installed (only the Command Line Tools), and working on High Sierra makes installation a little convoluted.
Later in the development process it became a point of pride.
I enjoy that my source directory is straightforward to navigate and free of .xcodeproj files!
Of course, this is a small and precarious joy, and ultimately it’s probably not worth it.
However, if you do want to take the road less advised, here are a couple learnings:

You can run that with swift example.swift and a little window will pop up!
The example includes no typical macOS keyboard shortcuts, so ⌘Q won’t work, but it’s nice that there’s no ViewController in sight.
In fact, there is no explicit ViewController in all of Multi!

macOS Notification Center limits which processes can send notifications.
To get things working, you’ll need a bundleIdentifier, which is generally supplied in your Info.plist file.
If you’re running everything from a single script though, you won’t have one.
Rizwan Sattar wrote a neat workaround that monkey-patches NSBundle, which I’ve translated to Swift 4 below:

Edit: someone on Hacker News suggested that this is a more future-proof method.
In either case, the final version of Multi does not use this workaround because it generates a valid Info.plist file.

It’s been a while since I’ve written any Swift, and I enjoyed getting back into it.
It was fun to remember exactly why I loved extensions, and using AppKit for the first time helped me appreciate the gravity of SwiftUI.
Finally, if you check out Multi and/or have any ideas on how to make it nicer, please let me know!