#Start with the shape of the problem
If you're working out how to build a dynamic island for mac, the first thing to accept is that Apple gives you nothing to build on. There's no Dynamic Island framework, no notch API beyond a couple of geometry helpers, and no live-activity system on macOS at all. What you're really building is an illusion: a small, always-on-top window that sits under the physical camera housing and pretends to be part of it. Get the position, the shape, and the motion right and people read it as a system feature. Get any one of them wrong and it reads as a floating box.
I've built exactly this, NotchBay, and shipped it, so the rest of this is the architecture I'd hand a friend starting today, not theory. Four pieces carry the whole thing: the window, finding the notch, the animatable shape, and click-through. None is huge on its own; the difficulty is that all four have to be right at the same time.
#The panel: a borderless, transparent NSPanel
The container is a single NSPanel, not an NSWindow, because a panel can float above your other windows without stealing focus. Make it borderless and transparent, kill the shadow, and park it at a high window level so it stays above ordinary app windows:
// AppKit host for the island let panel = NSPanel( contentRect: rect, styleMask: [.borderless, .nonactivatingPanel], backing: .buffered, defer: false) panel.isOpaque = false panel.backgroundColor = .clear panel.hasShadow = false panel.level = .statusBar // above normal windows panel.collectionBehavior = [.canJoinAllSpaces, .stationary] panel.ignoresMouseEvents = true // pass clicks through by default
The .nonactivatingPanel flag is the one that saves you: without it, tapping the island yanks keyboard focus out of whatever you were doing. canJoinAllSpaces plus stationary keeps the island present when you switch desktops, which you want, since the notch is always physically there. Everything visible, the resting pill, the expanded card, a music waveform, is a SwiftUI view hosted inside this panel with an NSHostingView. I keep the panel itself dumb and do all layout and animation in SwiftUI.
#Finding the notch with NSScreen
You can't hardcode the notch position; it moves with screen size and scaled resolution. macOS exposes it through NSScreen. safeAreaInsets.top is the notch height, and auxiliaryTopLeftArea and auxiliaryTopRightArea are the two menu-bar slivers on either side of the camera, so the cutout width is the screen width minus both:
let screen = NSScreen.main! let notchHeight = screen.safeAreaInsets.top // 38 pt on a 16-inch if let l = screen.auxiliaryTopLeftArea, let r = screen.auxiliaryTopRightArea { let notchWidth = screen.frame.width - l.width - r.width // center a panel of this width at the top of the screen }
If safeAreaInsets.top comes back 0, that Mac has no notch, so either bail or fall back to a simulated pill near the menu bar. On real hardware this returns 220×38 points on the 16-inch MacBook Pro and 185×32 on the 14-inch; I measured the full set across models in the notch size breakdown. Recompute all of it whenever the screen parameters change (listen for didChangeScreenParametersNotification), because plugging in a display or changing resolution shifts everything.
#The shape, and the spring that stretches it
A plain rounded rectangle looks close but reads as wrong, because the real cutout isn't one. Its top corners are tighter than its bottom corners (roughly 4 pt versus 8 pt), and Apple uses continuous, squircle-style curvature rather than a plain arc. In SwiftUI the cheapest honest approximation is a continuous corner style:
RoundedRectangle(cornerRadius: 12, style: .continuous)
for the expanded states, with hand-tuned asymmetric corners on the resting pill so its top hugs the hardware. The .continuous style is doing real work; the default .circular corners are the giveaway that separates a convincing island from a floating badge.
Motion is the other half. The island's whole appeal is that it stretches: a compact pill snaps open into a wide card when a call arrives, then settles back. Drive that with SwiftUI springs, not linear curves, because the overshoot-and-settle is what sells it as physical:
withAnimation(.spring(response: 0.35, dampingFraction: 0.72)) {
state = .expanded
}Animate width, height, and corner radius together and let the spring carry them. I spent more time tuning response and dampingFraction than on any other pair of numbers: a hair too bouncy and it feels like a toy, a hair too stiff and it feels dead.
#Click-through, staying light, and permissions
Here's what the quick tutorials skip. Three things will eat your week:
- Click-through. The panel covers a strip of screen you don't own. If it swallows clicks, you've broken the menu bar and everything under it. ignoresMouseEvents = true handles the idle case, but the moment you show a real button you need the opposite. The clean fix is to override hitTest on the content view so only actual controls return a view; every transparent pixel returns nil and the click falls through to whatever's behind.
- Notch geometry per model. The 14-inch and 16-inch cutouts differ, the Air's differs again, and scaled resolutions move all of them. Anything you hardcode will be a point off on someone's machine, and at this size a point is visible. Derive it from NSScreen, every launch.
- Staying light. This runs all day. It has to idle at effectively zero CPU when nothing's happening and wake only for real events. Poll in a tight loop and you'll show up in everyone's battery complaints; prefer notifications and observers over timers.
- Permissions. The island itself needs none, but the features people want do. Now-playing info comes from MediaRemote-style plumbing Apple keeps semi-private; call controls that press another app's mute button need Accessibility; anything touching the mic triggers its own prompt. Each capability is a separate permission and a separate review headache.
#Or skip the build and use NotchBay
Building one is a genuinely fun AppKit-and-SwiftUI project, and if that's why you're here, go do it. But if you just want the feature on your Mac today, the honest answer is that a polished island is weeks of tuning, not an afternoon, and several good apps already exist:
- boring.notch is free and open source, so it doubles as a working reference: media controls, a file shelf, a HUD replacement.
- NotchNook and Alcove are the polished commercial options, refined widgets and files on one, animation and notifications on the other. Both sell one-time and subscription tiers; check their sites for current pricing, which moves around.
- DynamicLake Pro packs the most features per dollar, from media and files to Bluetooth and live activities.
- NotchBay, the one I build, is the work-focused pick: calendar with one-tap Join, Zoom and Meet controls from the notch, an OCR-searchable clipboard tray, on-device dictation, and drop-to-share via your own Google Drive. It's $19 one-time with a 3-day trial and needs macOS Tahoe (26). I'm upfront that it's newer than NotchNook and Alcove, and its Meet controls drive Chromium browsers only, not Safari.
If you want the landscape before deciding to build or buy, I wrote a full survey of the Dynamic Island for Mac category, a plain walkthrough of how to get one installed in five minutes, and a rundown of the free options. Any of those will tell you fast whether building it is worth your weekend.
#Frequently asked questions
Can I build a Dynamic Island for Mac without a private Apple API?
Yes. There is no public Dynamic Island API, but you don't need one. You pin your own borderless NSPanel just under the notch and draw everything yourself with SwiftUI. NSScreen tells you where the notch is; the rest is a normal, if fiddly, AppKit window.
How do I position a window exactly under the notch?
Read NSScreen.main. safeAreaInsets.top gives the notch height; auxiliaryTopLeftArea and auxiliaryTopRightArea bracket the camera housing, so the cutout width is screen width minus both. Center a panel of that width at the top of the screen and it lines up.
What window type should the panel be?
A borderless NSPanel with the nonactivatingPanel style, a clear background, no shadow, and a high window level near .statusBar. Set it to join all Spaces and stay stationary. It must never take key focus, or clicking it steals focus from your real work.
How do I make clicks pass through the transparent parts?
Two layers. Set the panel's ignoresMouseEvents when nothing interactive is showing, and for finer control override hitTest so only your actual controls return a view. Every transparent pixel returns nil and the click falls through to the window behind.
Which corner radius matches the real notch?
The hardware cutout is not a plain rounded rectangle: the top corners are tighter (about 4 pt) than the bottom (about 8 pt), and the shape uses continuous, squircle-style curvature. Match both or your island reads as almost-right, which is worse than obviously different.
Is it worth building versus buying a notch app?
If you want to learn AppKit and SwiftUI, absolutely. If you just want the feature, buying is cheaper in hours. A polished island means notch geometry per model, media and Accessibility permissions, low idle CPU, and multi-display edge cases, which is weeks, not an afternoon.