Architecture
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
Module resolution
SootSim’s Vite plugin handles:
- redirecting
react-nativeto SootSim’s RN shim - resolving
.ios.ts>.native.ts>.ts(metro-style) - stubbing native packages with compat stubs
- transforming CJS
require()to ESM imports - handling JSX in
.jsfiles from node_modules
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