$npx @angular/cli@latest new my-app$cd my-app && an init
25 primitives · 8 platforms · one Rust core
The whole argument
One template. Whatever that platform actually ships.
Nothing here is drawn to resemble a control. The template does not change between one platform and the next — what changes is the class the framework mounts, and where a platform has no equivalent, nothing is mounted and the host says why.
<an-view[style.gap]="'16'">
<an-text[fontSize]="28">Alerts</an-text>
<an-switch
[on]="alerts()"
(onChange)="alerts.set($event)"/>
</an-view>
an-switch becomes
UISwitch
The system's own switch: its animation, its haptic, its accessibility trait, and whatever it looks like in the next release of iOS.
MaterialSwitch
Material 3, resolved without Gradle. It follows the device theme, including the dynamic colour a user picked from their wallpaper.
NSSwitch
AppKit, in a window that resizes — with a pointer that has a shape and a hover state, both of which a finger does not have.
Toggle
The one host that is not a view hierarchy: the tree is mirrored into a model SwiftUI redraws.
UISwitch
The same host as the phone, in a windowed scene. A window in space is not a screen, but it is still UIKit.
MaterialSwitch
The phone's host on a round screen, where the safe area is how the bezel's margin arrives.
nothing is mounted
UISwitch is not in the tvOS SDK — a television is driven with a remote. The layout keeps the gap it had measured and the host says so once, in the log.
Real controls, not lookalikes
Nothing is drawn to resemble a control. The switch in your template is the system’s switch, so it looks and behaves however that control does in that version of the OS, and it ages with the platform instead of with this repository.
iOS · iPadOSUISwitch
AndroidMaterialSwitch
macOSNSSwitch
watchOSToggle
visionOSUISwitch
tvOSnot in the SDK
The layout is not the platform’s
UIKit, AppKit and Android lay out differently, and SwiftUI does not let you lay out at all — so layout leaves the platform entirely. Flexbox runs once, in a Rust core over taffy, and every host is handed absolute frames in logical points. The same template lays out identically on a phone, a TV and a watch.
Angular as it is
Signals, @if, @for, the router with parameters, AOT templates, dependency injection. Zoneless, and not optionally: without zone.js there are no timers or XHR to patch inside the engine, which is most of what makes this painful elsewhere. No dialect, no subset.
A gap is never silent
A prop no host reads, a style nobody recognises, an event a platform cannot deliver, a plugin missing a platform: each one warns, or stops the build. A primitive that is unsupported somewhere has to say so in writing, and scripts enforce it.
[angular-native] (pinch) does not arrive on watchOS:
MagnifyGesture is @available(watchOS, unavailable),
and two fingers do not fit on a 40 mm screen
Recorded on a simulator, not mocked up
Two apps out of examples/, running.
Both of these are ordinary Angular components — signals, @for, @if — and every control in them is the platform's own. The recordings are the iOS simulator, driven by hand: the search field is a UISearchBar, the size picker is a UISegmentedControl, the quantity is a UIStepper, and the stars are SF Symbols.
A gallery that reflows
Two columns dealt out by running height, a system search field, a category strip and pull-to-refresh. There is no grid in the layout engine and none is needed: a waterfall is two flex columns, resolved once in Rust.
The carousel is the one thing here that is not a system control, because no platform ships one — so it is a pan gesture moving a transform, and letting go hands the rest to the platform’s own drawing thread. The stepper and the switch beside it are UIKit’s.
The same bundle on all of them. What differs is not the code — it is which controls that platform ships, and every gap is listed with the reason for it.
iOS · iPadOS
Renders withUIKit
All 25 primitives
Android
Renders withandroid.view + Material 3
All 25 primitives
macOS
Renders withAppKit
All 25 primitives
tvOS
Renders withUIKit + focus engine
20 of 25 — a TV has no switch or slider
visionOS
Renders withUIKit in a windowed scene
All 25 primitives
watchOS
Renders withSwiftUI
17 of 25
Wear OS
Renders withandroid.view
18 of 25
HarmonyOS · Windows
Renders with—
Not started
In one minute
Four commands on a project you already had
An Angular CLI project, unmodified, running on native views. Nothing moves into this repository and ng build keeps working.
an init
Dependencies, tsconfig and an entry point. It touches neither src/main.ts nor angular.json.
an add ios
Writes ios/Info.plist, yours from then on.
an ios
Builds, assembles the .app without Xcode and launches it in the simulator.
Terminal window
npx@angular/cli@latestnewmy-app&&cdmy-app
aninit
anaddios
anios
Write Angular. Ship native.
An ordinary ng new project, four commands, and it is running on real UIKit and real Material views.