Skip to main content

Running Your App

One codebase, three targets. Each platform has its own dev loop, all driven by the sublime CLI. Whenever something looks off, sublime doctor checks your environment and platform toolchains.

Web

The web target runs your screens/web/ screens with the MUI theme generated from your tokens, behind the navigation.tsx (react-router) output of build:nav. Develop it with:

npm run dev:web # → sublime dev:web

sublime dev:web compiles the navigation, starts the Vite dev server, and keeps watching the storybooks — so any navigation change recompiles automatically while the server runs. (The generated nav files are git-ignored build artifacts; you no longer run build:nav by hand during development.)

Mobile

Mobile runs your screens/mobile/ screens with React Native + Paper.

Build an offline Android APK:

npx @sublime-ui/devkit build

sublime build produces an offline Android APK. To install and launch it on a connected device, use run:

npx @sublime-ui/devkit run

sublime run installs the build and launches it on the device.

Desktop

Desktop reuses your web UI inside an Electron shell (via Electron Forge) and adds a typed native bridge for Node/OS capabilities. There are no separate desktop screens.

Start the desktop app in development, with Forge and HMR:

npx @sublime-ui/devkit dev:desktop

sublime dev:desktop runs Forge start with hot module replacement, so edits to your web screens reload live in the desktop window. Like dev:web, it also recompiles navigation whenever a storybook changes. (Still aliased as desktop:dev.)

Package the app for distribution:

npx @sublime-ui/devkit build:desktop

sublime build:desktop runs Forge make to produce Windows, macOS, and Linux packages (a portable .zip on Windows/macOS, .deb/.rpm on Linux). To add a Windows installer, see Packaging.

Calling native code

From any screen, reach a native service with useNative — it returns null on plain web and a typed client on desktop, so the same screen code works on both:

import { useNative } from '@sublime-ui/desktop';
import type { Printer } from '../../native/printer.service';

const printer = useNative<Printer>('printer'); // null on plain web
await printer?.print(receipt);

Because the renderer imports only import type of a service, Node dependencies never leak into the web bundle. Built-in services include fs, dialog, shell, clipboard, and notifications.

The loop at a glance

PlatformDevelopBuild / Package
Websublime dev:websublime build:web (static site)
Mobilesublime runsublime build (offline Android APK)
Desktopsublime dev:desktopsublime build:desktop

The dev commands recompile navigation on every storybook change, so you rarely touch build:nav directly. Reach for sublime doctor whenever a toolchain needs a sanity check.