-
-
Notifications
You must be signed in to change notification settings - Fork 77
Development Guide
This guide covers everything needed to get Rein running locally, contribute code, and test across platforms.
| Tool | Version | Notes |
|---|---|---|
| Node.js | ≥ 18 | LTS recommended |
| npm | Bundled with Node | |
| GStreamer | 1.20+ | Auto-installed by postinstall on macOS/Windows; system package on Linux |
| Linux: uinput access | — | See Linux-specific setup below |
| macOS: Accessibility | — | Required for input injection |
# 1. Clone
git clone https://github.com/AOSSIE-Org/Rein.git
cd Rein
# 2. Install (also installs/checks GStreamer via postinstall)
npm install
# 3. Run dev server
npm run dev
# 4. Open in browser
open http://localhost:3000/settingsRein uses /dev/uinput for virtual input devices. Setup is required once:
# Create the uinput group
sudo groupadd -f uinput
# Set device permissions
sudo tee /etc/udev/rules.d/99-rein.rules <<EOF
KERNEL=="uinput", MODE="0660", GROUP="uinput"
EOF
# Add your user to the group
sudo usermod -aG uinput $USER
# Reload rules
sudo udevadm control --reload-rules
sudo udevadm trigger
# Log out and back in, then verify:
ls -l /dev/uinput
# Should show: crw-rw---- 1 root uinput ... /dev/uinputInstall via your package manager:
# Ubuntu / Debian
sudo apt install gstreamer1.0-tools gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \
gstreamer1.0-libav
# Fedora / RHEL
sudo dnf install gstreamer1 gstreamer1-plugins-base gstreamer1-plugins-good \
gstreamer1-plugins-bad-free gstreamer1-plugins-ugly
# Arch Linux
sudo pacman -S gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-uglyFor Wayland sessions, ensure:
systemctl --user status pipewire pipewire-pulse
systemctl --user status xdg-desktop-portal xdg-desktop-portal-gnome # or -kde, -wlr, etc.If the portal is not running, start it:
systemctl --user start xdg-desktop-portalA shell.nix is provided:
nix-shell
npm install
npm run devGrant Accessibility permission to your terminal or IDE:
System Settings → Privacy & Security → Accessibility → Add your terminal
GStreamer is automatically downloaded by npm install (postinstall script).
GStreamer is automatically downloaded by npm install.
For testing, ensure Windows Defender / antivirus doesn't block the GStreamer executable.
| Script | Command | Description |
|---|---|---|
predev |
biome check . --write |
Auto-format before dev |
dev |
vite dev --host |
Start Vite dev server |
build |
vite build |
Production build → .output/
|
start |
vite preview --host --open |
Preview production build |
electron |
npx electron . |
Run Electron (requires production build) |
electron-dev |
concurrently ... |
Run Electron with Vite dev server |
dist |
electron-builder |
Package Electron app |
test |
vitest run |
Run all tests |
check |
biome check . |
Lint & format check |
check:fix |
biome check . --write |
Auto-fix lint & format |
Rein/
├── electron/
│ └── main.cjs # Electron main process & server process launcher
├── public/
│ └── app_icon/ # Application icons
├── scripts/
│ └── install-gstreamer.js # GStreamer postinstall resolution script
├── src/
│ ├── components/
│ │ └── Trackpad/ # React Trackpad UI components
│ │ ├── Buffer.tsx
│ │ ├── ControlBar.tsx
│ │ ├── ErrorComponent.tsx
│ │ ├── ExtraKeys.tsx
│ │ ├── ScreenMirror.tsx
│ │ └── TouchArea.tsx
│ ├── contexts/
│ │ ├── ConnectionProvider.tsx # Dual DataChannel React context & RTT measurement
│ │ └── DebugContext.tsx # Client log interception & debug context provider
│ ├── hooks/
│ │ ├── useRemoteConnection.ts # Thin wrapper over ConnectionProvider
│ │ ├── useTrackpadGesture.ts # Touch gesture state machine & scroll locking
│ │ └── useWebRtcStream.ts # WebSocket signaling, RTCPeerConnection, freeze watchdog
│ ├── routes/
│ │ ├── __root.tsx # Root layout + navigation bar
│ │ ├── debug.tsx # Host telemetry chart, session snapshots, SSE log console
│ │ ├── index.tsx # Redirect to /settings
│ │ ├── settings.tsx # Settings UI & QR code generator
│ │ └── trackpad.tsx # Main remote trackpad control interface
│ ├── server/
│ │ ├── drivers/
│ │ │ ├── keyMap.ts # Logical key name → native code mapper
│ │ │ ├── utils.ts # Acceleration curve calculations
│ │ │ ├── linux/ # /dev/uinput virtual device driver via Koffi FFI
│ │ │ ├── mac/ # CoreGraphics CGEvent driver
│ │ │ └── windows/ # Win32 SendInput & Synthetic Pointer driver
│ │ ├── gstreamer/
│ │ │ ├── captureProvider.ts # Platform screen capture source factory
│ │ │ ├── gstManager.ts # gst-launch-1.0 process manager (x264enc + udpsink)
│ │ │ ├── gstPaths.ts # GStreamer binary & environment path resolver
│ │ │ └── utils.ts # Wayland XDG Desktop Portal & D-Bus helpers
│ │ ├── constants.ts # Server constants (RTP_HOST, RTP_PORT 5004)
│ │ ├── InputHandler.ts # 8ms throttle, gesture sanitization, driver dispatch
│ │ ├── server.ts # HTTP router, API handlers, SseTransport logging
│ │ ├── tokenStore.ts # Token CRUD, timing-safe compare, tokens.json persistence
│ │ ├── types.ts # Shared server-side TypeScript interfaces
│ │ └── webRTC.ts # werift WebRTC manager, WebSocket server (/ws), UDP relay
│ ├── utils/
│ │ ├── i18n.ts # Key-value internationalization helper
│ │ ├── logger.ts # Winston logger instance
│ │ ├── net.ts # UDP socket LAN IP detection helper
│ │ └── welcome.ts # CLI startup welcome banner
│ ├── config.tsx # App UI constants (themes, storage keys)
│ ├── router.tsx # TanStack Router setup
│ ├── routeTree.gen.ts # Auto-generated TanStack route tree
│ ├── server-config.json # Server configuration file
│ ├── styles.css # Global Tailwind CSS styles
│ ├── tokens.json # Persisted auth tokens (gitignored)
│ └── types.tsx # Global TypeScript types
├── biome.json # Biome linter/formatter config
├── package.json
├── postcss.config.js
├── shell.nix # Nix development environment
├── tsconfig.json
└── vite.config.ts # Vite build config + signaling middleware plugin
npm run testUses Vitest with jsdom. Test files follow the *.test.ts / *.spec.ts convention.
- Set VirtualBox network adapter to Bridged Adapter
- Select your active Wi-Fi or Ethernet interface
- Run
npm run devin the VM - Find the VM's LAN IP:
ip addrorhostname -I - Connect your phone to the same Wi-Fi
- Navigate to
http://<VM_IP>:3000/settings
If GStreamer is not available, the pipeline falls back to videotestsrc pattern=ball — an animated ball pattern. This allows testing the WebRTC data channel input path without a real screen capture.
Rein uses Biome for linting and formatting:
npm run check # Check only
npm run check:fix # Auto-fixKey style rules:
- ES6+ syntax,
constpreferred overlet - No
anytypes - Arrow functions for callbacks
- No
console.login committed code (uselogger.ts) - Keep functions small and focused
- Join the Discord server (Project → Rein) — mandatory
- Find or create an issue
- Fork the repo and create a feature branch
- Make changes, run
npm run check:fixandnpm run test - Submit a PR with a clear description
- Post your PR link in the Discord channel
See CONTRIBUTING.md for the full guide.
| Variable | Used By | Description |
|---|---|---|
DISPLAY |
GStreamer (X11) | X11 display (default :0) |
XAUTHORITY |
GStreamer (X11) | X11 auth cookie path |
XDG_SESSION_TYPE |
CaptureProvider | Detect Wayland session |
WAYLAND_DISPLAY |
CaptureProvider | Detect Wayland session |
GST_PLUGIN_PATH |
GstManager | GStreamer plugin search path |
GST_PLUGIN_SCANNER |
GstManager | GStreamer plugin scanner binary |
VITE_DEV_SERVER_URL |
Electron dev | URL for Electron to load |
HOST |
Nitro production | Server bind address |
PORT |
Nitro production | Server port |