Architecture
The full pipeline — react-reconciler building SootSimNode trees, Yoga flexbox, CanvasKit/Skia rendering, scroll physics, the responder touch system, the Animated API, how your app bundle loads, and the test bridge.
Rendering pipeline
Key components
Reconciler (engine/reconciler.ts)
SootSim uses react-reconciler to build a custom React renderer. Instead of creating DOM elements or native views, it creates SootSimNode instances.
The reconciler handles:
- creating/updating/removing nodes
- managing the node tree hierarchy
- scheduling commits (batched updates)
Node tree (engine/node.ts)
SootSimNode is the core data structure. Each node has:
type— component type (View, Text, Image, etc.)props— React propsstyle— resolved styleslayout— computed layout from Yogachildren— child nodes
Layout engine (engine/yoga-layout.ts)
Uses Yoga (the same layout engine as React Native) to compute flexbox layouts. Every node gets a Yoga node, styles are applied, and layout is computed in a single pass.
Canvas renderer (engine/canvaskit-renderer.ts)
Renders the node tree to a <canvas> element using CanvasKit (Skia compiled to WebAssembly). Handles:
- background colors, borders, border radius
- text rendering with proper fonts
- image loading and display
- shadows and opacity
- scroll clipping
- scroll fade gradients
Scroll physics (engine/scroll.ts)
Implements iOS scroll behavior:
- momentum scrolling with deceleration
- rubber band effect at bounds
- snap-to-page
- scroll indicators
Touch system (engine/touch/)
Implements the React Native responder system:
- hit testing through the node tree
- responder negotiation (onStartShouldSetResponder, etc.)
- touch event propagation
Animation (engine/animated.ts)
Implements the Animated API:
Animated.Valuewith listenersAnimated.timing(),Animated.spring(),Animated.sequence()useNativeDriversupport (renders animations in the canvas frame loop)- interpolation and color interpolation
Loading your app
SootSim works like React Native: you point it at a JS bundle URL and it runs that bundle. The bundle is produced by your own bundler — Metro, Expo, or One — the same way you would build for a device. SootSim has no opinion about how you bundle.
The React Native runtime your app imports (View, Text, ScrollView, the
Animated API, and native-module behavior) is provided by SootSim’s engine, so a
standard React Native bundle runs unchanged.
Testing infrastructure
Test bridge (src/test-bridge.ts)
Exposes window.__sootsimTest with methods to query the node tree from Playwright tests. All test drivers (Detox, Maestro, raw Playwright) use this bridge.
Detox driver (test/detox-driver/)
Drop-in replacement for the detox package. Remaps Detox’s element/matcher/expect API to SootSim’s test bridge.
Maestro driver (test/maestro-driver/)
Runs Maestro-compatible YAML flows by:
- parsing YAML into step objects
- executing each step against the SootSim test bridge
- coordinating with Playwright for screenshots and video