Devices/SDK

SDK

The TypeScript library your app page bundles, the protocol and the harness.

Devices pages

@evolent/os-app is the small TypeScript library an app page uses to run inside the Evolent OS (laptops, computers, the tablet, and full screen on terminals). Protocol 1, SDK 1.0.0. It is MIT licensed, so your app can carry any licence.

Installation

Add it to the devDependencies of your page's Vite project, with the path from your page's folder to the sdk/ folder of evolent_devices:

package.json
"@evolent/os-app": "file:../../evolent_devices/sdk"

Then import { connectApp } from '@evolent/os-app'. It is bundled into your build. The example app evolent_os_hello is a Svelte 5 page set up this way.

A page that is not built can copy dist/os-app.js next to itself and import from ./os-app.js, or load dist/os-app.iife.js with a script tag and use window.EvolentOS.connectApp().

Never load it at run time from https://cfx-nui-evolent_devices/...: bundle it, so your page keeps working with the host stopped and needs no cross-origin module load.

Usage

main.ts
import { connectApp } from '@evolent/os-app';

const os = connectApp();

os.onOpen(({ context }) => show(context.greeting));
os.on('greet', (data) => greet(data.name));

const reply = await os.post('roll', { side: 6 });

os.publish({ rolled: true });
  • context is what your server's onOpen returned.
  • os.on('greet', ...) gets your client's exports.evolent_devices:sendAppMessage(app, { action = 'greet', data = ... }).
  • os.post('roll') reaches your resource's RegisterNUICallback('roll'), or the host relay.
  • os.publish is seen by people within 12 m, so never send names, money, ids, plates or typed text.

Outside the game os.hosted is false and post() is a normal NUI fetch.

Fonts

Your page is its own document and gets no fonts from the host. To match the OS, bundle Poppins and JetBrains Mono (SIL Open Font License) in your resource with @font-face and list the files in files, as the example app does from web/public/fonts.

API

Properties

PropertyDescription
hostedfalse outside the game.
modeuse, watch, or ''.
kind, appThe device kind and your app id.
transportframe, direct (terminals) or none.
inputdui on laptops and computers, native on the tablet.
token, contextThe session token and what onOpen returned.
user{ name, initials }.
locale, brand, scaleThe OS texts, the server brand and the page scale.
opened, relayedWhether the page is open, and whether posts go through the host relay.
studioThe first view of the 3D studio on a terminal, or null.

Methods

MethodDescription
on(action, fn)Pushes with { action, data }.
onMessage(fn)Every other push.
onOpen(fn), onClose(fn)The session opens or closes.
onIntent(fn)An intent from openApp(appId, intent) or a notification.
onVisibility(fn)Minimised, locked or no signal.
onState(fn)The published state, in watch mode.
post(name, data?, { readOnly?, timeout? })Calls your NUI callback, or the relay.
publish(state)Shares a small state with people nearby.
notify(notice)A notification from the page.
recent({ title, sub?, intent? })An entry in the launcher's recent list.
badge(count)A count on your app icon.
privatePointer(on)Hides the pointer from people nearby while a code is typed.
studioSend(action)Drives the 3D studio on a terminal.
close(), leave()Closes the app, or leaves the device.
ready()With connectApp({ manualReady: true }), tells the host the page is ready.
disconnect()Stops listening.

The types are in sdk/dist/os-app.d.ts.

The harness

The harness is a host emulator for a normal browser. In the web/ folder of evolent_devices run npm run dev and open /preview/harness.html?load=1 on the address Vite prints. It loads the app page twice: the user's window and the watch copy that people nearby get. It answers hello with os:open and the context you type, sends typed keys as os:key, sends your own messages and intents, answers every post with the reply you set, and shows the published state and every message from the app.

The app page must come from the same server, because the SDK trusts the harness origin only with ?harness=1, which the harness adds. By default it loads a sample app. For your own page, add its folder to server.fs.allow in web/vite.config.ts and pass ?url=/@fs/ followed by the full path to its web/build/index.html. Other query parameters: app, kind, input, width, height.

Building the SDK

In the web/ folder of evolent_devices: npm run build:sdk. It writes dist/os-app.js and dist/os-app.iife.js (Chromium 103, not minified). App pages bundle the SDK when they are built, so rebuild them after an SDK change.

Protocol 1

For your own SDK. Every protocol message is a plain object with __os: 1, type and the session token.

Within protocol 1 changes only add; both sides ignore what they do not know. A page that says another protocol gets "This app needs an update" in its window.