GitHunt
OP

open-source-labs/Reactime-Native

A browser-based debugging tool for React Native applications that visualizes component state changes and performance metrics in real time using a timeline scrubber.

Reactime Native (Alpha)

A React Native time-travel debugger inspired by Reactime.
Unlike the original Chrome extension, this project targets React Native apps (Expo, Metro, Hermes) and runs with no native code โ€” only JavaScript.

This project is currently in alpha. The team is actively building out important features and plan to package for npm soon.


Status

Alpha stage. Not production-ready. The team is building toward an npm package release.

Currently you can:

  • Stream React Native state snapshots over WebSocket
  • Scrub through state history in a browser-based debugger
  • Capture early performance metrics (commit duration, lag)
  • Manage snapshot history with Redux Toolkit on the frontend

Architecture

graph LR
    A[React Native App] -->|Redux middleware| B[WS Client]
    B -->|ws://host:8080| C[Node.js Server<br/>port 8080]
    C -->|broadcast| D[Browser Debugger<br/>localhost:5173]
    D -->|Redux slice| E[Timeline UI]
Loading

Reactime Native is split into three moving parts:

  1. Agent (inside RN app)

    • Hooks into the React DevTools global hook (__REACT_DEVTOOLS_GLOBAL_HOOK__)
    • Intercepts Fiber commits
    • Traverses the Fiber tree to collect props/state
    • Serializes snapshots and streams them over WebSocket
  2. WebSocket server

    • Simple Node server that relays snapshots from RN โ†’ browser UI
    • Acts as the "bridge" layer between environments
  3. Debugger UI (browser)

    • Built with React + Vite
    • Uses Redux Toolkit slices to store snapshots, metrics, and UI state
    • Provides timeline scrubber, import/export, and basic controls

Snapshot capture + replay flow

sequenceDiagram
    participant RN as React Native App
    participant S  as WS Server
    participant UI as Browser Debugger

    RN->>S: {channel:'snapshot', type:'add', payload}
    S->>UI: broadcast snapshot
    UI->>UI: dispatch addSnapshot โ†’ Redux store
    UI->>UI: TimelineSlider updates

    Note over UI: Developer scrubs timeline

    Note over UI,RN: ๐Ÿšง Planned (v0.2.0) โ€” bidirectional replay not yet implemented
    UI-->>S: {channel:'snapshot', type:'jumpTo', payload:{index}}
    S-->>RN: forward jumpTo command
Loading

Key Features

  • WebSocket relay โ€” real-time, bidirectional bridge between the RN app and browser debugger using the native WebSocket API (no Socket.IO)
  • Redux Toolkit โ€” centralized snapshot history, timeline index, and performance metrics shared across all browser UI components via feature slices
  • TypeScript strict mode โ€” end-to-end typed: RN middleware, WebSocket server contracts, Redux slices, and all browser UI components
  • Snapshot diff view โ€” color-coded line-level diff between consecutive snapshots (added / removed / changed / unchanged) with recursive nested object support
  • Component tree โ€” collapsible component hierarchy rendered from snapshot data; nodes with state changes highlighted with a visual badge
  • Keyboard accessibility (WCAG 2.1.1) โ€” timeline scrubber supports arrow key navigation; component tree supports ArrowRight/Left/Enter/Space; all interactive controls have visible focus rings
  • Vitest test suite โ€” unit and integration tests across all three packages with environment-specific configs (jsdom for browser client, node for RN + server)
  • Dynamic IP resolution โ€” wsConfig.ts fallback chain (EXPO_PUBLIC_WS_HOST โ†’ Expo hostUri โ†’ Android emulator โ†’ localhost) eliminates hardcoded IPs across dev environments

Fiber: What We're Capturing

React uses an internal Fiber tree to track every component instance.

  • Think of it as React's equivalent of the DOM tree: each node holds props, state, hooks, and children.
  • On every commit, React walks this tree to decide what to update on screen.

In our agent code (MobileSample.tsx), we:

  • Subscribe to onCommitFiberRoot
  • Traverse the Fiber tree for only the stateful components
  • Convert each new commit as a "snapshot" and feed in a serialized JSON representation
  • Broadcast snapshots to the WebSocket server

The frontend debugger UI then reconstructs these snapshots into a timeline view.


Architecture Decisions

Decision Choice Rationale
Transport Native WebSocket API No Socket.IO overhead; reliable RN compatibility
MVP scope One-way flow (RN โ†’ browser) Delivers core observability value without blocking on bidirectional complexity
IP resolution wsConfig.ts fallback chain Eliminates hardcoded IPs; any dev sets EXPO_PUBLIC_WS_HOST in .env.local
Server design createServer() factory + require.main guard Separates library behavior from CLI; makes broadcast() unit-testable
Browser state Redux Toolkit slices Shared snapshot history + metrics across multiple components without prop drilling

See CLAUDE.md for the full engineering decision log.


Environment Variables

Variable Where Description
EXPO_PUBLIC_WS_HOST sample-RN-app/.env.local Override WebSocket host (LAN IP or hostname). Strips any leading scheme or embedded port automatically.

The browser client connects to ws://localhost:8080 by default. Update client/src/transport/socket.ts if your server runs on a different host.


Running Tests

Each package has its own Vitest config with environment-specific settings
(jsdom for the browser client, node + React Native stubs for the RN app).
Do not run npx vitest from the repo root โ€” there is no root-level config,
so Vitest will pick up all test files without the correct environments and
produce misleading failures.

Use the per-package scripts instead:

# Browser client tests (jsdom environment)
npm run test:client

# React Native app tests (node environment + RN stubs)
npm run test:rn

# Both in sequence
npm test

Getting Started (Dev Setup)

โš ๏ธ MVP still in progress โ€” setup may change.

  1. Clone the repo.
  2. Start the project:
    # 1) WebSocket server
    cd server && node server.js
    
    # 2) Sample React Native app (or use the hook to access the Fiber tree of your own RN app)
    #    By default the app auto-detects the dev server host via Expo's hostUri.
    #    To override (e.g. on a physical device):
    #    EXPO_PUBLIC_WS_HOST=192.168.1.42 npx expo start
    cd sample-RN-app && npx expo start
    
    # 3) Debugger UI (located at localhost:5173)
    cd client && npm run dev

Roadmap / Planned Features

Shipped

  • Component tree visualization โ€” collapsible component hierarchy with changed-state highlighting
  • Snapshot diff view โ€” color-coded line-level diff between consecutive snapshots (added / removed / changed)
  • Timeline controls โ€” play/pause, speed control (0.5x / 1x / 2x), keyboard navigation

Planned

  • Full fiber tree capture โ€” serialize the complete React component tree (props + state at every node), not just stateful nodes; Will's feat/fiber-capture branch
  • Bidirectional time-travel โ€” replay state back into the running RN app
  • Expanded metrics โ€” fibers updated per commit, event loop lag, app-level profiling
  • Snapshot persistence โ€” optionally store history to disk for long debugging sessions
  • Packaging & distribution โ€” publish as an npm package for easy setup with any RN project

License

This project is licensed under the MIT License - see the LICENSE file for details.

open-source-labs/Reactime-Native | GitHunt