← Back to Dark Matter

Quick Start

Zero to OTA update in 5 minutes.
Let's ship.

✦

What You'll Build

By the end of this guide, you'll have:

Prerequisites: A React Native app (Expo or bare workflow).
β—‡

Step 1: Install the CLI

One command installs the Dark Matter CLI:

$ curl -fsSL https://dark-matter.io/install.sh | sh

This downloads the CLI for your platform and adds it to your PATH.

macOS only for now. Linux and Windows coming soon.
✧

Step 2: Install the SDK

Add Dark Matter to your React Native app:

$ npm install darkmatter-react-native

Or with yarn:

$ yarn add darkmatter-react-native
β—‡

Step 3: Set Up Your Account

Launch Dark Matter from your React Native project root:

$ darkmatter

On first launch, the setup wizard guides you through:

╔═══════════════════════════════════════════════════════════════╗
β•‘ β•‘
β•‘ Β· ˚ ✦ DARK MATTER ✦ ˚ Β· β•‘
β•‘ Over-the-air updates for React Native β•‘
β•‘ β•‘
β•‘ Let's get you set up. This takes about 90 seconds. β•‘
β•‘ β•‘
β•‘ ──────────────────────────────────────────────── β•‘
β•‘ β•‘
β•‘ β—‰ Create new account β•‘
β•‘ β—― I have an API key β•‘
β•‘ β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
  1. Enter your email β€” We'll send a 6-digit verification code
  2. Enter the code β€” Check your inbox, no password needed
  3. Name your app β€” How it appears in your dashboard

When complete, the wizard creates a config file in your project:

βœ“ Config written to ./darkmatter.config.js
That's it! No manual credential copying. No web portal. Your app is configured and ready to receive updates.
✦

Step 4: Initialize in Your App

Add Dark Matter to your app's entry point (usually App.tsx or index.js):

import { useEffect } from 'react';
import { initialize, useUpdate } from 'darkmatter-react-native';

// Initialize once at app start
initialize({
  baseUrl: 'https://api.dark-matter.io/functions/v1',
  appId: 'your-app-id',  // From setup wizard
  channel: 'production',
});

export default function App() {
  const { status, check, apply } = useUpdate();

  // Check for updates on mount
  useEffect(() => { check(); }, []);

  if (status.type === 'ready') {
    return <Button title="Restart to Update" onPress={() => apply({ restartImmediately: true })} />;
  }

  return <YourApp />;
}

Your app will:

Tip: The appId is shown in the setup wizard after you name your app. It's the slugified version of your app name.
β—‡

Step 5: Bundle Your App

Create a JavaScript bundle for your React Native app:

For iOS

$ npx react-native bundle \
    --platform ios \
    --dev false \
    --entry-file index.js \
    --bundle-output dist/main.jsbundle \
    --assets-dest dist/

For Android

$ npx react-native bundle \
    --platform android \
    --dev false \
    --entry-file index.js \
    --bundle-output dist/index.android.bundle \
    --assets-dest dist/

Create the archive

$ cd dist && tar -czf ../release.tar.gz . && cd ..
✧

Step 6: Deploy Your Update

This is the moment. Launch Dark Matter:

$ darkmatter

Navigate to the Deploy tab and fill out the form:

╔═══════════════════════════════════════════════════════════════╗
β•‘ Deploy β”‚ Releases β”‚ Metrics β”‚ Settings β•‘
╠═══════════════════════════════════════════════════════════════╣
β•‘ Bundle: release.tar.gz β•‘
β•‘ Platform: iOS β•‘
β•‘ Channel: production β•‘
β•‘ Version: 1.0.0 β•‘
β•‘ Rollout: β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ 100% β•‘
β•‘ β•‘
β•‘ [Deploy Release] β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
  1. Bundle: Select your release.tar.gz file
  2. Platform: Choose iOS or Android
  3. Channel: production, beta, or staging
  4. Version: Semantic version (e.g., 1.0.0)
  5. Rollout: Percentage of users (start with 10% for safety)

Press Enter on Deploy Release and watch the magic:

Quantum tunneling through the cloud...
β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘β–‘β–‘ 80%
βœ“ Update live! Deployed to 10% of users.
β—‡

You Did It

Your first OTA update is live. Users with your app will receive the update on their next launchβ€”no app store, no waiting, no friction.

What just happened?
✦

Next Steps

Monitor Your Releases

The Metrics tab shows real-time adoption data:

Manage Rollouts

Use the Releases tab to adjust rollout percentages or disable releases:

Multiple Channels

Use channels to test updates before production:

Gradual Rollouts

Start at 10%, monitor for issues, then increase to 25%, 50%, 100%. The TUI makes it one keystroke to adjust.

β—‡

TUI Keyboard Shortcuts

Tab / Shift+Tab β€” Switch tabs
1 2 3 4 β€” Jump to tab
↑ ↓ β€” Navigate
Enter β€” Select/Activate
q β€” Quit
? β€” Help
✧

Need Help?

We're here for you:

"Ship code like it's 2025. Because it is."