One Logo Pool Ball
wwwwwwwwwwwwwwwwwww

One Native

How One's native APIs are named, packaged, and linked

One ships native iOS and Android APIs alongside the framework. They cover platform views (SwiftUI, Compose), shared views that work on both platforms, and platform modules (notifications, clipboard, camera, and more).

Components and services use the One namespace; hooks are named imports from one:

import { One, useSizeClass } from 'one'
One.UI.Image // shared by both platforms
One.iOS.Toggle // iOS only
One.Android.Switch // Android only
One.Notifications.schedule(...) // shared module
function Layout() {
const sizeClass = useSizeClass()
return sizeClass.horizontal === 'regular' ? <Wide /> : <Narrow />
}

Naming rule

The namespace tells you where an API runs:

Platform-only components stay strict: SwiftUI components throw outside iOS builds and Compose components throw outside Android builds, so keep those branches behind platform checks. The UIKit toolbar host, menu actions, and zoom transition components (One.iOS.ToolbarHost, One.iOS.MenuAction, and the ZoomTransition* components) return null instead, so they are safe to keep in cross-platform trees.

Uniform services have no aliases under One.iOS. A service awaiting a native implementation on a platform follows the no-native contract: effects do nothing, reads return empty or denied values, and calls requiring a result reject with <Namespace>.<verb> needs an iOS or Android build. Security operations fail closed. One.iOS keeps the generated iOS framework mappings where they exist.

One.platform reads the current platform: 'web', 'ios', 'android', or 'rnx'.

import { One } from 'one'
if (One.platform === 'ios') {
return <One.iOS.Toggle label="Airplane mode" isOn={on} onIsOnChange={setOn} />
}
return <One.Android.Switch isOn={on} onIsOnChange={setOn} />

Packaging

Install one and the native code comes with it: the iOS and Android sources, the generated bindings, and the libraries One builds on (Nitro Modules, Nitro Image, OP SQLite). There is nothing else to install.

Non-view modules (clipboard, haptics, notifications, and the rest) are Nitro hybrid objects: a TypeScript spec declares the interface, and Nitrogen generates the Swift and Kotlin bindings. Views are Fabric components: their specs declare props and events, and React Native codegen produces the native view managers. The iOS controls mirror SwiftUI’s names and prop contracts, and the Android views mirror Compose’s.

Linking

The native code links during the native build through React Native autolinking: One ships a podspec, an Android Gradle module, and a codegen config, so one prebuild wires it into the generated Xcode and Android Studio projects. Expo apps use Expo prebuild with the vxrn/expo-plugin adapter instead; see Build or Run iOS and Ship with EAS.

Feature flags live in the app manifest under native.app. Examples: the Android maps key (android.googleMapsApiKey), the camera permission string (imagePicker.camera), push (notifications.push), and the SplitView gamma flag (ios.screensGamma). Each page shows the keys it needs. Without a key, the guarded call rejects or throws instead of crashing.

On web there is no native runtime. Shared views either render a web fallback, render nothing, or throw; modules resolve inert values (denied permissions, empty lists) or no-op. Each page documents its web behavior.

Edit this page on GitHub.