Legend SparkExperimental

React Native, meet the desktop.

Spark gives React Native apps real windows, menus, dialogs, and files on the Mac. Start in a prebuilt runner with Fast Refresh, then ship a standalone .app.

App.tsx
import { AppRegistry, Text } from 'react-native'
import { createMenu } from '@legendapp/spark/menus'
import { openWindow } from '@legendapp/spark/windows'

AppRegistry.registerComponent('Inspector', () => () => <Text>Inspector</Text>)

createMenu({
  id: 'editor',
  items: [{
    type: 'submenu', id: 'view', label: 'View',
    items: [{ type: 'action', id: 'inspector',
              label: 'Show Inspector', shortcut: 'CmdOrCtrl+I' }],
  }],
  onAction: ({ itemId }) => {
    if (itemId === 'inspector') {
      // A second native window, rendering a React Native root
      openWindow({
        id: 'inspector',
        component: 'Inspector',
        title: 'Inspector',
        size: { width: 480, height: 640 },
      })
    }
  },
}).catch(console.error)
Current source API · see Getting started

One package, the whole desktop.

Import each capability from @legendapp/spark. Typed and async, with explicit ownership and cleanup.

All capabilities
Windows/windows
Named windows, displays, geometry, close guards, and native macOS chrome.
Menus/menus
The app menu bar, context menus, tray items, and Dock menus.
Shortcuts/shortcuts
Local and global accelerators, with command routing.
Files and dialogs/files
Open and save panels, atomic writes, streams, watching, and Trash.
Settings/settings
JSON settings, Legend State persistence, and secure storage.
Updates/updates
Native whole-app updates for the apps you ship.

One project, three ways to run it.

Move from a shared runner to your own build only when the project needs it. Spark checks native requirements before loading JavaScript.

  1. 01 / SPARK RUNNER

    Start without Xcode

    A prebuilt development app. Create a project, run it, and edit App.tsx with Fast Refresh.

    $ npm create @legendapp/spark@next MyApp
    $ cd MyApp
    $ npm run macos
  2. 02 / CUSTOM DEVELOPMENT BUILD

    Add native when you need it

    Extra native modules or helper executables need an app-specific build. JavaScript changes still use Fast Refresh.

    $ npx --no-install spark build --dev --platform macos
  3. 03 / STANDALONE APP

    Ship a real Mac app

    Build a .app with embedded JavaScript, then sign and notarize it with your own Developer ID.

    $ npm run build
    $ npm run package

No browser inside.

React Native all the way downScreens are React Native views and your JavaScript runs in Hermes. Node runs the tooling and is never bundled into the app.

The Expo workflow you knowExpo Desktop generates the native host and Expo CLI owns Metro, logs, and reload. Spark adds desktop APIs and runtime selection.

Where it stands

Spark is experimental and not ready for production; APIs can still change. macOS 14+ on Apple Silicon is the primary target. Intel Mac builds and Windows development exist in source, with native acceptance pending.

The @next preview uses matching SDK archives and downloads the macOS Apple Silicon Spark Runner on first launch. Signed distribution acceptance remains pending.

Status and limitations