How Yantra Apps Are Built: Surfaces, One Kit, and No Restart
The architecture behind the apps beside your chat: independently deployed remotes, a shared kit for sign-in and chat, and registration without a restart.
Yantra Team3 min read
On this page
There are more than forty apps in the Yantra launcher, and they were not built by one team in one repository. This post explains the architecture that makes that possible, for developers curious about how the pieces fit.
Apps are remotes
Internally an app is called a surface. A surface is a separately built and deployed bundle that the Yantra shell loads at runtime through Module Federation. The shell does not import a surface's source; it fetches the surface's remote entry from a URL when the app is opened. That is why a new surface can appear in the launcher without a release of the shell, and why a surface can be versioned and deployed on its own cadence.
Each surface is a package with its own dependencies, its own build, and a pure page component that has no federation imports. The federated entries live in a small exposes folder, so the page can also be rendered anywhere else.
One kit, three lines of config
Every surface consumes the same kit. It provides a Vite and Module Federation config factory, so a surface's build config is a few lines; a Tailwind token preset, so a surface looks like the shell under all five themes and dark mode; a TypeScript base; a federated style injector; and the runtime pieces every app needs: sign-in, connector calls, the shared chat pane, the connect-connector modal, open links and the recorder engine.
The kit is what lets a surface run in three places with one codebase: hosted inside the shell, standalone on its own page, and inside the desktop app.
Registration without a restart
A surface reaches a workspace in one of two ways. The older way is an environment variable on the shell that points at the surface's remote entry, which needs a restart. The newer way is a marketplace contribution: publish the surface to the config registry under its slug and the shell picks it up, with no restart and no code change. A generic route renders any surface published this way.
Deploying is a single command that builds, refuses to ship a bundle that carries a localhost URL or a baked credential, uploads the bundle, and submits it. Nobody needs cluster access to ship an app.
The one rule about chat
Only one chat is ever on screen. A surface declares whether it owns the chat. If it does, the shell folds its own chat column away and hands the conversation to the surface, which renders it with its own templates and toolbox. If it does not, the shell's chat stays beside the panel and the surface sends requests into it. A surface never mounts its own chat next to the shell's.
This is why "move it to Thursday" works in Calendar and "cut this to one page" works in Resume: the surface and the agent share one conversation and one view.
Sign-in and open links
Standalone, a surface shows a sign-in gate and uses the normal app login with an OAuth consent screen where you pick a project and environment. Tokens renew silently while the app session is valid.
Open links solve a different problem: the agent wants to hand you an app on a phone that has never signed in. The link and a confirmation code are delivered separately, the link works once within ten minutes, and it grants a session of twelve hours by default. Five wrong codes burn the link.
Where things are kept
Each surface stores its own files. A separate index records which canvases, trips, designs, meetings and resumes exist, who owns them and where their files live, so "my trips" can be listed anywhere you sign in. Some surfaces have a backend of their own, such as the travel data layer, the shopping deals store, the telephony server behind Voice Ops, or the orchestrator behind DealDesk. A small subgraph kit points each surface at the right backend for the site it is served from, so a staging build promoted to production never talks to development data.
What this buys
A team can build an app against the kit, run it standalone with a demo agent on sample data, publish it to a workspace, and have it open beside every conversation in that workspace, without touching the shell. The shell's job shrinks to routing, chat and the launcher. The apps do the rest.
Read more in Apps Overview.