Skip to content

Use the Desktop Bridge

This page is the bridge reference for the frontron support package.

If you created your app with create-frontron, this is the bridge API the starter is already wired for. If you retrofitted an existing frontend, this is the same supported renderer contract you should target.

If you are new to Electron-style apps, read Understand the Bridge Flow first.

The short rule is still simple: renderer code should use only frontron/client.

1. Import the bridge

ts
import { bridge } from 'frontron/client'

Do not read preload globals directly.

Do not use window.electron.

2. Built-in bridge APIs

These namespaces are built into frontron.

bridge.system

  • getVersion()
  • getPlatform()
  • getNativeStatus()
  • isNativeReady()
  • openExternal(url | { url })

bridge.window

  • minimize()
  • toggleMaximize()
  • hide()
  • getState()
  • onMaximizedChanged(listener)

bridge.window is still the primary-window convenience API.

bridge.windows

  • open({ name })
  • show({ name })
  • hide({ name })
  • focus({ name })
  • close({ name })
  • minimize({ name })
  • toggleMaximize({ name })
  • exists({ name })
  • getState({ name })
  • listConfigured()
  • listOpen()

Use this namespace when your starter or manual config defines more than one named window.

bridge.native

  • getStatus()
  • isReady()
  • add(left, right)

3. Example built-in calls

ts
import { bridge } from 'frontron/client'

const version = await bridge.system.getVersion()
const state = await bridge.window.getState()
const nativeStatus = await bridge.native.getStatus()
await bridge.windows.open({ name: 'settings' })

These methods work without project-specific bridge code.

4. Add a custom bridge namespace

Custom bridge code has two parts:

  1. register the bridge in config
  2. export handlers from frontron/bridge/

Register it in config

ts
// frontron.config.ts
import { defineConfig } from 'frontron'
import bridge from './frontron/bridge'

export default defineConfig({
  app: {
    name: 'My App',
    id: 'com.example.myapp',
  },
  bridge,
})

Export handlers

ts
// frontron/bridge/index.ts
const bridge = {
  app: {
    getGreeting: () => 'Hello from desktop code',
  },
}

export default bridge

Call it from the renderer

ts
import { bridge } from 'frontron/client'

const greeting = await bridge.app.getGreeting()

5. Add Rust-backed bridge methods

Use rust.bridge when the handler should come from frontron/rust.

ts
import { defineConfig } from 'frontron'

export default defineConfig({
  rust: {
    enabled: true,
    bridge: {
      math: {
        add: {
          symbol: 'frontron_native_add',
          args: ['int', 'int'] as const,
          returns: 'int' as const,
        },
      },
    },
  },
})

Then the renderer can call:

ts
import { bridge } from 'frontron/client'

const sum = await bridge.math.add(2, 3)

6. Built-ins versus starter examples

Some bridge methods shown in the starter are examples, not built-in package APIs.

For example:

  • bridge.system.cpuCount() comes from starter config
  • bridge.math.add() comes from rust.bridge
  • bridge.file.hasTxtExtension() comes from starter config

Those methods exist only if your project config registers them.

7. Generated types

frontron writes .frontron/types/frontron-client.d.ts during:

  • frontron dev
  • frontron build
  • frontron dev --check
  • frontron build --check

That file gives autocomplete for custom namespaces and generated method signatures.

8. When the bridge looks missing

If the UI says Desktop bridge unavailable or Missing bridge handler, check these first:

  1. run npm run app:dev, not npm run dev
  2. import from frontron/client
  3. register your custom bridge in config
  4. check the terminal for preload or runtime errors

TIP

Start with bridge.system and bridge.window.

Move to custom bridge namespaces only when the app needs project-specific desktop calls.

Released under the MIT License.