Desktop integrations
Oro Runtime applications stay web-first, but the point of the runtime is that you do not stop at the browser boundary. This guide shows how to add four integrations users actually notice: notifications, clipboard, file pickers, and native menus.
1) Request and use notifications#
src/main.js:
import Notification, { showNotification } from 'oro:notification'
import { onNotificationResponse } from 'oro:hooks'
const permission = await Notification.requestPermission()
if (permission === 'granted') {
await showNotification('Field Notes ready', {
body: 'Capture notes even when the main window is not focused.',
})
}
onNotificationResponse((event) => {
console.log('notification response', event)
})
Make sure your project enables notifications:
[permissions]
allow_notifications = true
2) Copy useful content to the clipboard#
Clipboard integration is one of the fastest ways to make a utility app feel native:
import { writeText, readText, canWriteText } from 'oro:clipboard'
async function copyCurrentNote(note) {
if (!canWriteText()) return
await writeText(`${note.title}\n\n${note.body}`)
}
console.log(await readText())
3) Let the user choose files with the native picker#
Use the current window to open platform file pickers:
import application from 'oro:application'
const currentWindow = await application.getCurrentWindow()
const paths = await currentWindow.showOpenFilePicker({ multiple: true })
console.log(paths)
This is the right path when the user is selecting files outside the application bundle or filesystem sandbox.
4) Add a native application menu#
Menus matter on desktop. They make the app feel intentional instead of embedded:
import application from 'oro:application'
await application.setSystemMenu({
index: 0,
value: `
File:
New Note: n + Meta;
Sync Now: s + Meta;
Quit: q + Meta;
Edit:
Copy Summary: c + Meta;
`,
})
Use menu items for high-frequency actions, not every control in the UI.
5) Pull the integrations together#
Here is a realistic pattern for a note-taking app:
import { writeText } from 'oro:clipboard'
import { showNotification } from 'oro:notification'
async function exportNoteSummary(note) {
await writeText(`${note.title}\n${note.updatedAt}`)
await showNotification('Copied summary', {
body: `Copied "${note.title}" to the clipboard.`,
})
}
That one flow crosses UI, clipboard, and notifications without dropping into native platform code.
Considerations#
- Gate integrations behind permissions where the runtime requires them.
- Use notifications for user value, not background noise.
- Keep menu labels and button labels aligned so keyboard and UI navigation tell the same story.
Next#
Source repository · Edit this page · View Markdown