Chapter 5 Desktop integrations
5
Chapter 5

Desktop integrations

Native app behavior should stay explicit in the source. This chapter adds permissions, notifications, clipboard access, and a small application menu without leaving the web programming model.

Enable the capabilities

Permissions belong in configuration so reviewers can see what the app asks the host to do.

oro.toml
[permissions]
allow_notifications = true
allow_clipboard = true

Notify when work is saved

Ask for permission once, then send notifications for user-visible outcomes.

src/main.js
import Notification, { showNotification } from 'oro:notification'

const permission = await Notification.requestPermission()

async function notifySaved(note) {
  if (permission !== 'granted') return

  await showNotification('Field note saved', {
    body: note.title,
  })
}

Copy a useful summary

Clipboard actions are best when they match a clear user command.

src/main.js
import { writeText, canWriteText } from 'oro:clipboard'

async function copySummary(note) {
  if (!canWriteText()) return

  await writeText(`${note.title}\n${note.updatedAt}`)
}

Add a menu command

Desktop menus should mirror high-frequency UI actions, not duplicate every button.

src/main.js
import application from 'oro:application'

await application.setSystemMenu({
  index: 0,
  value: `
    File:
      New Note: n + Meta;
      Quit: q + Meta;
    Edit:
      Copy Summary: c + Meta;
  `,
})

The app is still web code. Runtime modules mark the places where the app crosses into host behavior, which keeps native access readable during review.

What changed

  • Permissions moved into reviewed config.
  • Notifications became tied to saved work.
  • Clipboard access became an explicit command.
  • The native menu matched the app's repeated actions.

Chapter complete

You now have the core Runtime learning path. Continue into the docs for storage, service workers, and packaging.

Continue in docs