Summary
Craft renders mobile UI with WKWebView on iOS and WebView on Android. It exposes native components — but they are desktop chrome, created imperatively one instance at a time. There is no general native view tree, so a UI framework targeting Craft can only draw into a web view.
That is the gap between "web app in a native shell" and "native app", and it is the thing a React Native-style framework needs from its host.
What exists today
packages/typescript/src/components/native.ts gives typed bindings for SplitView, FileBrowser, OutlineView — desktop surfaces, each createX(config) returning an instance with methods. Genuinely useful, and not a view tree: no View / Text / Image / TextInput primitives, no layout engine, no way to mount a hierarchy and then mutate it efficiently.
packages/ios/templates/CraftApp.swift is WKWebView throughout — the web view is the UI (makeUIView at :585, the scheme handler at :482, navigation delegates at :1686). packages/ios/README.md lists what the bridge does expose, and it is capability rather than UI: speech recognition, haptics, camera, barcode scanning, geolocation, motion, file pickers.
Why this matters now
We are building stx-native — .stx templates compiled to native views, React Native-shaped. Its compiler already produces a correct view IR with resolved flex layout and colours. It has renderers for UIKit and Android written, and nothing to mount them into: Craft gives us the process, the lifecycle, the packaging and the device bridge, and then hands us a web view to draw in.
Craft is otherwise exactly the right host. This is the one missing piece.
Ask
A view-host bridge — the host side of what React Native calls the shadow tree:
- Node operations, batched:
createNode(type, props),updateNode(id, props),insertChild(parent, child, index),removeNode(id). Batched because a reactive framework produces many small mutations per frame and a round trip each is the thing that makes these architectures feel slow. - A layout engine — Yoga is the obvious choice, already how React Native and Litho do flex on both platforms, and the IR we generate is already flex-shaped.
- A primitive set:
View,Text,Image,ScrollView,TextInput, and a recycling list. The list is the one that cannot be faked — a long feed is where a WebView loses. - Event delivery back over the existing bridge, so a tap on a native view can invoke a JS handler.
Prior art worth reading before designing it: React Native's UIManager and the newer Fabric renderer, and NativeScript's view hierarchy API.
Related, and probably a prerequisite: rendering native views while still running JS inside a WKWebView means shipping a web view purely as a JavaScript engine. Filed separately.