Inside
LanaiIntelligence
The only package allowed to import Vision, NaturalLanguage, CoreML, or the Apple Intelligence Foundation Models. Every AI capability lives behind a small protocol here. Implementations are unsurprising. So are the mocks.
Engineering
Lanai is a single SwiftUI multiplatform target with about eighty percent of its code shared across iPhone, iPad, and Mac. Persistence is SwiftData. The AT Protocol SDK sits behind a small facade so it can be replaced without anyone above noticing. All on-device AI lives in one package; only that package may import the frameworks that do the inference. The rest of the app uses a public interface and a mock.
This page is the posture, not the implementation. The shape of the work is enough; the recipes belong somewhere else.
Six commitments that show up in every package, every release, and every decision worth arguing about.
SwiftUI, SwiftData, AVFoundation, Vision, NaturalLanguage, the Apple Intelligence Foundation Models, Liquid Glass. A single multiplatform target builds for iPhone, iPad, and Mac. Not Catalyst. Not a web wrapper. The platform is the partner.
Around 80% of the code is identical across iPhone, iPad, and Mac. What differs is the chrome — bottom tab bar on iPhone, three-column NavigationSplitView on iPad and Mac, Reeder-style J/K keyboard nav on the desktop, a real Mac Settings window. Platform differences live in a single adapter package; everything else is universal.
Lanai talks to the AT Protocol through a small facade. Feature code never imports the SDK directly; it imports a value-typed model layer that could be backed by a different AT Protocol library tomorrow. The choice of SDK is an implementation detail. The choice to abstract it away is the architecture.
Every AI-touching capability lives in one package. Only that package is allowed to import the on-device frameworks. Other packages use a small public interface. The seam is where the privacy posture is enforced — not in documentation, in the import graph.
When Lanai cleans up the display of a post — curly quotes, real em dashes, generous leading, optical alignment — the cleanup happens at the moment of rendering. The post on the network is unchanged. Long-press any post in the app to see the original, character for character.
The largest Dynamic Type size, AX5, is the size every layout is composed at first. The default-size layout is the derivative. Body text targets APCA Lc≥75 with Lc≥90 on high-contrast surfaces. Reduce Motion is honoured at every animation site, not as a fallback but as a real path through the same design.
The shorthand version. Each row names what's there and why, without naming what's coming next.
Lanai is composed of local Swift packages, each with its own imports, its own tests, and its own rules. The boundaries between them are the places the architecture lives.
The facade. Auth, fetching, posting. Wraps the upstream AT Protocol SDK. Returns value-typed models from a sibling package so feature code never touches the SDK directly.
Pure value types — Post, Profile, Feed, ThreadGate, MuteList. No UI, no SDK imports. Could ship as its own library.
SwiftData stack and offline cache. The single source of truth for local state.
Tokens, themes, type ramp, motion. The vocabulary every feature speaks. New surfaces start by reaching into this package.
The only package allowed to import Vision, NaturalLanguage, CoreML, or Apple Intelligence. Every AI capability the app uses sits behind a protocol here. The architectural enforcement of the on-device promise.
The thin layer where iPhone, iPad, and Mac differences live. Image types, share sheets, haptics. Everything else above the line is universal.
The architectural decision the rest of the app depends on.
Inside
The only package allowed to import Vision, NaturalLanguage, CoreML, or the Apple Intelligence Foundation Models. Every AI capability lives behind a small protocol here. Implementations are unsurprising. So are the mocks.
Outside
Compose, Timeline, Profile, Settings, Export. Every other package imports the public interface only. The on-device frameworks are out of reach, by build-time guarantee.
The point of the seam isn’t the abstraction. The point is that the privacy posture is enforced at the import graph, not at the description. A future feature that wanted to send something off-device would have to do so visibly, in the one room where it could be reviewed.
The architecture is shaped as much by what isn’t there as by what is. A short list of decisions that didn’t happen.