Skip to main content

The app is the only interface, on the web and on Android

Mission Control had two interfaces: the web app (apps/web, React and TanStack Router on a design system of its own, packages/ui) and, since October 2026, the Expo app (apps/app), built for Android and, through react-native-web, for the browser at /next. Keeping both meant building every feature twice in two design languages, and the person using it daily had moved to the app on both the phone and the desk. We decided that the app is the only interface: its web build is served at the root, and the web app and its design system are deleted rather than kept at /classic for a while. Before deleting them, every capability of the web app was listed and each one either built into the app or dropped by name (docs/spec/app-transition.md, phase 8).

Considered Options​

  • Keep the web app at /classic for a period, as first planned: rejected by the person using it daily. Nothing it does is missing from the app once the gaps are closed, and a second interface left running goes stale without anyone looking at it.
  • Keep the web app as the desktop interface and the app for the phone: rejected. The app lays out for wide screens itself (a sidebar beside every screen, a task beside its list), and two interfaces for one product double every change.
  • Delete the web app at once, with what it did and the app does not: rejected. Pull requests on a task, its links, sign-offs and tags, a conversation's followed tasks and archived messages, and more were built into the app first; what was dropped was dropped as a decision (comment tags, a getting-started checklist, deleting a conversation, browser notifications for now, the command palette).

Consequences​

  • The server serves the app from its root. A path that is no file is the app's page, where Expo Router takes over; /next/…, where the app was first served, redirects to the same path. The page is isolated across origins everywhere, as the replica's SQLite in the browser needs.
  • The server package ships the app's web build, not the app. @ai/mc-server-cli copies apps/app/dist into its own frontend/ when it builds, so the image carries the files and none of the app's dependencies.
  • Links from the web app keep working. Its #/<organization>/… addresses open the same place in the app, in that organization.
  • Development runs the app in Expo's dev server, which passes /api on to the local server.
  • The documentation's screenshots come from the app. Its pipeline, the recorded agent runs and the scenario they play in, moved to the app's end-to-end tests.
  • One design language. The app's tokens took over the web app's colours, which the documentation site keeps wearing.