Skip to content

Mobile App (jarvis-node-mobile)

The Jarvis Automation mobile app is built with Expo/React Native and runs on iOS and Android. It is the companion app for chatting with Jarvis, setting up and managing voice nodes, receiving notifications, and browsing deep research results. It talks to one server: jarvisd, the Jarvis Automation server.

Jarvis Automation is a pre-release (release candidate rc18.17). Server builds are on the releases page; each one is marked Pre-release. Get the app from the App Store or Google Play.

Connect to your server

The app asks for one address, the server's, and finds everything else from it:

  1. On the first screen, tap Set Server URL.
  2. Enter http://<server>:7700, where <server> is the IP address or hostname of the machine running jarvisd (for example http://192.168.1.100:7700), and tap Save.
  3. Log In, or Create Account with an invite code from a household admin. Only the first account on a new server can sign up without one (see Authentication).

The app does not search the network for the server: the address you pin is the only one it uses, so it never connects to a different server than the one it shows. To change it later, tap the address on the first screen, or use Settings → Config Service URL. If the app says it can't reach the server, check that the phone is on the same network and run jarvisd doctor on the server.

When the app sets up a voice node, it gives the node this same address.

Features

  • Node provisioning -- set up new Pi nodes over their Wi-Fi hotspot and give them your Wi-Fi and the server's address (see Provisioning)
  • Settings sync -- View and edit node command settings via encrypted snapshots (K2 key)
  • Push notifications -- Receive alerts from Jarvis (sent by jarvisd through the push relay)
  • Inbox -- Browse deep research results and other long-form content
  • Home Assistant -- Device discovery and smart home control
  • Node management -- View paired nodes, rooms, and device status

Screenshots

Home screen

Home — chat interface with voice and text input

Devices

Devices — smart home control by room

Routines

Routines — on-demand and scheduled automations

Nodes

Nodes — voice nodes and computers

Inbox

Inbox — deep research results and alerts

Settings

Settings — account, theme, and connection status

Tech Stack

Technology Version Purpose
Expo 54 Build toolchain and native modules
React Native 0.81 Cross-platform UI
React 19 Component framework
TypeScript — Type safety
React Navigation 7 — Bottom tabs + native stacks
React Native Paper — Material Design UI components
React Query 5 — Server state management
expo-camera — Scanning K2 key backup QR codes
expo-secure-store — Token storage in platform keychain

Architecture

jarvis-node-mobile/
├── App.tsx                    # Root providers (Auth, Config, Theme, Query)
├── src/
│   ├── auth/                  # AuthContext, token management
│   ├── screens/
│   │   ├── Auth/              # Login, registration
│   │   ├── Home/              # Main dashboard
│   │   ├── Devices/           # Smart-home devices
│   │   ├── Provisioning/      # Node setup flow
│   │   ├── SmartHome/         # Home Assistant integration
│   │   ├── ImportKey/         # K2 key import
│   │   ├── Inbox/             # Inbox items and their screens
│   │   ├── Nodes/             # Nodes tab, node detail and settings, Add a computer
│   │   ├── Routines/          # Routines tab
│   │   ├── Schedules/         # Scheduled errands
│   │   ├── Store/             # Pantry tab
│   │   ├── Memories/, Phonebook/, CallContext/, RecentCommands/, CommandData/
│   │   └── Settings/          # App settings
│   ├── navigation/            # Tab layout + stack navigators
│   ├── services/
│   │   ├── configDiscoveryService.ts   # Resolve services from the pinned server URL
│   │   ├── configPushService.ts        # Push config to nodes
│   │   ├── haApiService.ts             # Home Assistant API
│   │   ├── haDiscoveryService.ts       # HA auto-discovery
│   │   ├── oauthService.ts             # OAuth flows for commands
│   │   └── qrImportService.ts          # QR code parsing
│   ├── components/            # Reusable UI components
│   ├── contexts/              # ConfigContext (global config state)
│   ├── hooks/                 # Custom React hooks
│   └── api/                   # API clients
├── modules/
│   └── jarvis-crypto/         # Native encryption module
└── __tests__/                 # Jest test suite

Settings Sync (K2 Encryption)

The mobile app and Pi Zero nodes share a symmetric encryption key called K2 (AES-256). This key is exchanged during provisioning and used to encrypt settings snapshots in transit.

The flow:

  1. User taps a node in the mobile app to view its settings
  2. Mobile requests a snapshot from the server
  3. The server notifies the node via MQTT
  4. Node builds a settings snapshot, encrypts it with K2, uploads it to the server
  5. Mobile polls for the snapshot, decrypts with K2, and displays the settings

For development, generate K2 manually:

cd jarvis-node-setup
python utils/generate_dev_k2.py

Then import the key into the mobile app via the Import Key screen (Nodes tab > Import Key > paste the base64url string in the DEV input).

OAuth Flow Execution

Some commands require OAuth tokens (e.g., email, calendar). The mobile app handles the OAuth authorization flow:

  1. The server reports that a command needs OAuth
  2. Mobile app opens the OAuth provider's authorization URL
  3. User grants access in the browser
  4. Mobile app captures the redirect and finishes the flow for that provider

How the tokens are handled depends on the provider. For Home Assistant, the app itself exchanges the code with Home Assistant and creates a long-lived access token, which it uses to import your devices, so for that provider the tokens pass through the app.

Push Notifications

The mobile app registers for push notifications with jarvisd:

  1. App registers its Expo push token with the server
  2. Jarvis sends notifications (e.g., deep research complete, timer alerts)
  3. jarvisd forwards them to the push relay (jarvis-notifications-relay) for Expo Push API delivery
  4. User taps the notification to open the relevant screen (e.g., inbox detail)

Inbox

The Inbox tab displays long-form results from deep research queries and other asynchronous operations. Items are stored on jarvisd and fetched over its REST API.

Inbox detail

Inbox items with category chips (deep research, alert, reminder) and relative timestamps

Development

# Install dependencies
npm install

# Start Expo dev server
npm start

# Run on iOS Simulator
npm run ios

# Run on Android Emulator
npm run android

# Run tests
npm test
npm run test:coverage

E2E / CI server URL (EXPO_PUBLIC_MANUAL_CONFIG_URL)

The app has no network discovery: it resolves every service from the server URL the user pinned. In DEV_MODE only, a build with no pinned URL falls back to a baked one, so a fresh clearState e2e build can still reach the server in CI.

Set EXPO_PUBLIC_MANUAL_CONFIG_URL to the server's base URL (port 7700) before building. The development-e2e EAS profile sets this automatically:

// eas.json — development-e2e profile
"EXPO_PUBLIC_MANUAL_CONFIG_URL": "http://localhost:7700"

URL priority order (DEV_MODE only):

  1. UI-pinned URL (AsyncStorage) — always wins; a developer's manually-pinned URL is never overridden
  2. EXPO_PUBLIC_MANUAL_CONFIG_URL — baked fallback for e2e / CI builds with no pinned URL

With neither, the app asks for a URL. This variable is inert in production builds: DEV_MODE is false and production EAS profiles never set EXPO_PUBLIC_MANUAL_CONFIG_URL.

What the app reaches

Everything is on the one jarvisd server. The app starts from the address you pinned (port 7700), which tells it where the rest is.

Port Required Purpose
7700 Yes The server address you enter; it lists the other services
Sign-in, from 7700 Yes Login, token management
Others, from 7700 No Node registration and settings sync, push notifications and the inbox