Desktop
Add Electron authentication, browser handoff, and desktop navigation to your app
Use Desktop to connect your web app to an Electron companion. The plugin owns browser authentication, session transfer, renderer session synchronization, and desktop link behavior. The companion owns windows, preload bridges, deep links, packaging, and updates.
Installation
Choose Electron when creating your app, or add Desktop to an existing app:
bunx chat-js@alpha add desktop
The CLI installs chatjs/plugins/desktop/, its /device-login route, and authentication registrations. It also creates an electron/ companion directory when one does not already exist. Adding the plugin again preserves an existing companion. Desktop adds no database tables or migrations.
Start your web app, then launch the companion in another terminal:
cd electron
bun install
bun run dev
The companion loads http://localhost:3000 in development. Set ELECTRON_APP_URL when your web app runs at another address. See Desktop Distribution for icons, installers, signing, and releases.
Authentication
The native login and registration pages open your default browser. The browser performs the ordinary social sign-in and hands the session back through Better Auth’s Electron integration with PKCE. If you are already signed in in the browser, you can continue with that account.
The plugin allows /device-login and login or registration requests carrying its client_id through the app’s login redirect. Better Auth still validates the transfer and exchange. The server accepts only the exact synthetic origin for your configured desktop protocol.
Native sign-out runs through the preload bridge. A failed native sign-out leaves the current page in place and reports the failure. Successful sign-out clears the app’s caches and navigates to login. A later session-refresh failure does not undo a completed sign-out.
Configuration
Set appName, appPrefix, and appUrl in chat.config.ts. appPrefix is your desktop protocol scheme, so use the same configuration for the deployed web app and desktop build.
The companion’s prebuild reads those values and chatjs/plugins/desktop/protocol.ts, then writes electron/branding.json. The native runtime reads that generated file. Rebuild the companion after changing the app identity or protocol settings.
Desktop is enabled by installation. There is no desktopApp.enabled flag.
File ownership
| Location | Responsibility |
|---|---|
chatjs/plugins/desktop/auth-server.ts |
Better Auth integration, exact origin validation, auth route matching |
chatjs/plugins/desktop/desktop-auth-client.ts |
Browser transfer client |
chatjs/plugins/desktop/auth-form.tsx, auth-ui.tsx |
Native login and browser account handoff |
chatjs/plugins/desktop/auth-handler.tsx |
Renderer session synchronization and overlay |
chatjs/plugins/desktop/device-login-page.tsx |
Transfer completion and error states |
chatjs/plugins/desktop/sign-out.ts |
Native sign-out and session refresh |
chatjs/plugins/desktop/navigation.ts |
Modified-link handling in native windows |
chatjs/plugins/desktop/protocol.ts, bridge.ts |
Shared protocol settings, renderer bridge types, and renderer detection |
app/(auth)/device-login/page.tsx |
Thin route adapter |
electron/ |
Companion source and build tooling |
Repository contributors edit the canonical web plugin in packages/registry/src/plugins/desktop/src/ and run bun demo:sync. The reference companion remains in apps/electron/.
Integration points
Desktop provides server authentication, an authentication form wrapper and sign-out handler, modified-link navigation, and a layout component. These are explicit contracts in the Plugin API. Each authentication or navigation slot accepts one provider. The layout placement is shared with other plugins.
Navigation and sign-out import renderer detection from the dependency-free bridge module. The form and sign-out handler have separate generated imports; neither navigation nor sign-out imports the client factory, login form, or session overlay. The client factory owns only the layout contribution. Core retains its regular web authentication and form presentation.
Without Desktop
A new web-only app contains no desktop plugin, device-login route, Electron companion, or @better-auth/electron dependency. Generated defaults render the normal web forms, use web sign-out, and preserve ordinary browser link behavior. Core account authentication and chat ownership remain available. Guest sessions require the separate Guest Chat plugin.