Boundless now runs on iPad and Mac

Boundless runs natively on iPad, and on Apple Silicon Macs as the iPad app, with layout that adapts to a wide window instead of stretching to fill it.

Update, September 4, 2026. Boundless v2.15.0 is a complete rewrite on React Native. This post describes the SwiftUI app that came before it. The behaviour it argues for is still how the app works; the code it names is gone.

Boundless was an iPhone app. It now runs natively on iPad, and on an Apple Silicon Mac, where it runs as the iPad app rather than as a separate Mac build.

Getting it to launch on a bigger screen is the easy half. Getting it to look like it belongs there is the work.

Layout that adapts instead of stretching

A phone layout doesn't become an iPad layout just because you gave it more room. Left alone, SwiftUI will cheerfully stretch everything to whatever width is available, and what you get is a reader that's technically running on a large display and unusable on one.

So there's a shared width modifier now, applied in the places where width actually hurts:

  • Long-form settings screens are capped and centred. A settings row with its label at the far left and its toggle eighteen inches away isn't a settings row.
  • The prose reader's text column is capped too. Line length is a typography problem, not a window problem, and novel text running the full width of a large window is genuinely harder to read.
  • The library grid adds columns instead of stretching cells. It used to be three columns at any size. Now the count scales with the width, so covers stay cover-sized and you just see more of them.
  • Reader edge tap zones are capped. Proportional tap regions are correct on a phone and absurd on a large display, where "proportional" turns into several hundred points of screen that silently turns the page.

The root view had to claim the window

This is the detail that cost me the most time, and it's the kind of thing that only turns up on a real machine.

In a resizable window, SwiftUI doesn't automatically stretch content past its ideal size the way it does on a phone, where the scene is always exactly the size of the screen. The app launched perfectly well, and then rendered in a narrow column in the middle of a much wider window with bare backdrop around it. A screenshot made it obvious in about a second. Reasoning about the layout had gotten me nowhere.

The fix is unglamorous. The root view now explicitly claims the full window size instead of leaning on an assumption inherited from the phone. Everything below it was already adaptive and started behaving immediately.

Most of this work went like that, honestly. It wasn't writing large-screen code so much as finding all the places where the iPhone version had quietly assumed the phone was the only shape that exists.

Why not a separate Mac build

There was a Mac Catalyst target for a while, and it is gone again.

Catalyst gives you a real Mac app, and in exchange it asks you to maintain a second set of behaviours: the display-sleep API that works on iOS does nothing there, the embedded browser is unreliable, alternate app icons are unsupported. Each one is a fork in the code, and each fork is a thing that can rot without anyone noticing, because it only runs on the platform you test least.

Running as the iPad app deletes all of that. One code path, one set of behaviours, and the adaptive layout above is what makes it feel right on a big screen anyway. That layout work was never Catalyst-specific, which is why none of it was lost when the target went away.

Everything else is the same app, with the same local library and the same sources you added yourself. Availability is tracked on /download, and the feature docs are at /docs.