Publish an app
The App Store is driven by one file: registry.json at the repo
root. It lists every app, and the @react-ui-os/cli
bundles their source from it. Adding an app is two steps: write the app, then
add a manifest entry.
1. Author the app
Section titled “1. Author the app”An app is one App object plus whatever component tree it needs. Keep each app
in its own folder so its files copy together and the relative imports survive
the move.
"use client";
import type { App } from "@react-ui-os/core";import { useTheme } from "@react-ui-os/desktop";
function WeatherContent() { const theme = useTheme(); return <div style={{ color: theme.palette.textPrimary, padding: 8 }}>Sunny, 21°</div>;}
export const weatherApp: App = { id: "weather", name: "Weather", tagline: "Today at a glance", accent: "#38bdf8", defaultBounds: { w: 360, h: 420 }, content: WeatherContent,};Read colors, radii, and motion from useTheme() rather than hardcoding them,
guard any window/document access for SSR, and persist state through the
storage adapter instead of localStorage directly.
The apps under packages/example-apps/src are working references for the
two-pane layout, persistence, and keyboard handling.
2. Add a manifest entry
Section titled “2. Add a manifest entry”Append an entry to the apps array in registry.json:
{ "id": "weather", "name": "Weather", "description": "Today at a glance.", "category": "utilities", "accent": "#38bdf8", "export": "weatherApp", "dependencies": ["@react-ui-os/core", "@react-ui-os/desktop"], "dir": "packages/example-apps/src/weather", "files": ["index.tsx"]}| Field | Meaning |
|---|---|
id | Install id and the folder name the CLI writes to |
export | The named export the consumer registers with <Desktop> |
category | One word, used by the gallery filter |
accent | Hex color for the gallery card |
dependencies | npm packages the app imports (always core and desktop) |
dir | Source folder, relative to the repo root |
files | The files in dir to copy, by name |
The CLI copies these files into the consumer’s os-apps/<id>/ folder, so the
./icon and ./store relative imports keep working after the copy.
3. Try it locally
Section titled “3. Try it locally”The CLI installs from any registry, not just the built-in one. Point --registry
at your local registry.json; it reads the app sources from each entry’s dir,
so there is no build step for local testing:
npx @react-ui-os/cli add weather --registry ./registry.json --dir /tmp/tryHost your own registry
Section titled “Host your own registry”You do not need to add your app to this repository. Build your registry into a single self-contained file (every app’s source inlined) and host it anywhere that serves files over HTTP: GitHub Pages, a CDN, an object store.
npx @react-ui-os/cli build registry.json --out public/registry.jsonPublish public/registry.json, then anyone installs from it:
npx @react-ui-os/cli add weather --registry https://you.example/registry.jsonnpx @react-ui-os/cli list --registry https://you.example/registry.jsonA remote registry must be the built (inlined) form, because the CLI cannot read
your repository’s files over HTTP. The build command produces it.
Propose for the official registry
Section titled “Propose for the official registry”The built-in registry is curated and intentionally small. If an app is broadly
useful and matches the design discipline in DESIGN.md, open a pull request
that adds its source and the registry.json entry. A test guards the manifest
against drift (every listed file must exist, and every file in the app folder
must be listed); CI runs it and the build on every PR.
pnpm --filter @react-ui-os/example-apps test # the drift guard