Headless apps.
The same app, the same window.Arda, with nothing to draw on: a box that syncs and prints, a sensor that pushes readings. The page's scripts run in the player's own JavaScript runtime.
Running one
$ ardaplayer -headless myapp/
level=INFO msg="headless: running" script=main.js
level=INFO msg=app msg="started"
The player loads app/index.html and runs its classic <script> elements in order (inline or src from the folder). -dev changes nothing here (the player says so); arda.dev.json's settings and webhooks still apply to a local run.
A deployed app on a device with no screen
From v1.1.17 a device with no screen — a kiosk that finds none, or ardaplayer -headless with no folder — runs the app deployed to it through this same runtime, by the same rule as a folder: index.html's classic <script> elements, inline or a local src, in document order. Modules and scripts from another site are skipped.
Arda.headlessis true before the first line, andArda.configis the device's settings.- An app already installed when the device starts runs at once. The first app pushed to a new device waits until its
needForBootdata has arrived, as a screen's boot screen does. - Each update restarts the app on the new version. The update negotiation is the same as on a screen:
'updateStart'is heard,pause()andapply()work. location.reload()starts the app again. Locking the device in the portal stops it until it is unlocked.- Not in developer mode:
-devruns a folder.
What differs: there is no DOM
// Arda.headless is true before your first line; undefined in a page.
if (!Arda.headless) {
document.getElementById('total').textContent = '0'; // only with a screen
}
function tick() {
readSensor().then(function (v) {
return Arda.db.push('readings', { value: v, at: new Date().toISOString() }, 'r-' + Date.now());
}).catch(function (e) { console.error('reading failed:', e.message); });
}
setInterval(tick, 60000);
console.log('started');
documentis not stubbed: touching it throws, with a message naming the fix. A stub that did nothing would give an app that seems to run and achieves nothing.- Put the logic that must run without a screen outside your DOM code, in classic scripts.
<script type="module">is skipped with a warning, and so is a script from another site. - The engine is ES5.1 plus much of ES6.
??works, so theArda.configidiom is safe. console.*goes to the player's log (on a device, the journal); it is the only way a headless app is heard. See logging.- An uncaught throw is logged and the runtime keeps going, so a screenless device stays connected to report it.
Arda.keyboard()rejects; there is nothing to draw on.
fetch and WebSocket
// Your own servers, the same way a page would (a per-device setting holds the token)
fetch('https://api.example.com/orders', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + (Arda.config.api_token ?? ''), 'Content-Type': 'application/json' },
body: JSON.stringify({ till: Arda.config.till_name ?? 'till' })
}).then(function (r) { return r.ok ? r.json() : null; })
.then(function (orders) { if (orders) console.log('orders', orders.length); });
function connect() {
var ws = new WebSocket('wss://live.example.com/station');
ws.onmessage = function (e) { /* e.data: a string, or an ArrayBuffer for binary */ };
ws.onclose = function () { setTimeout(connect, 2000); }; // your app reconnects
}
connect();
fetchtakesmethod,headers,body(string, ArrayBuffer or typed array) andsignal; the response hasok,status,statusText,url,headers.get(),text(),json(),arrayBuffer(). A relative URL is the player itself (/storage/…). No CORS, no cookies; a request gives up after 2 minutes.WebSocketis the browser's API. Binary messages arrive as anArrayBuffer(there is no Blob). Headless only, a third argument{headers: {…}}adds handshake headers.setTimeout,setInterval,EventSource,AbortController,TextEncoderandTextDecoder(UTF-8) are there.- A socket does not survive the device going offline; a pushed record does. Keep what must not be lost in a dataset.
Checked: the examples on this site's other pages were run in this runtime (ardaplayer -dev -headless on a test folder): Arda.headless, Arda.config from arda.dev.json, Arda.db, fetch('/storage/…'), webhooks, and the document error. The v1.1.17 deployed-app behaviour is from the player's source (cmd/ardaplayer/headless.go, internal/jsrun/supervise.go) and its desk run against a test server; it has not run on a device. The fetch to an outside server and the WebSocket example were not run here.