Quickstart.
From an empty directory to an application running full screen on a device. Fifteen minutes if the hardware is already provisioned, plus however long your build takes.
Before you start
You need three things: an ArdaForm account (early access, for now), at least one registered device, and any toolchain that produces static HTML, CSS and JavaScript. Vite, esbuild, a Makefile or a folder of hand-written files all work identically — ArdaPlayer loads the output, not the tooling.
Install the CLI
The CLI is a single static binary with no runtime dependency.
$ curl -fsSL https://ardaform.net/install.sh | sh
$ arda version
arda 0.4.0-preview linux/amd64
$ arda login
Opening browser for authentication…
✓ authenticated as [email protected]
On a CI runner, skip arda login and set ARDA_TOKEN in the environment instead.
Create a project
$ arda init counter-kiosk
created counter-kiosk/arda.json
created counter-kiosk/src/index.html
created counter-kiosk/src/app.js
created counter-kiosk/src/style.css
$ cd counter-kiosk
$ arda link
fleet counter-kiosk
channel beta
✓ workspace linked
The manifest
arda.json is the only file ArdaForm requires. It names the application, points at the entry HTML, and — most importantly — declares which device capabilities the package may use.
{
"name": "counter-kiosk",
"version": "0.1.0",
"entry": "src/index.html",
// Run before packaging. Omit if you have no build step.
"build": "npm run build",
"root": "dist",
// Anything not listed here is absent at runtime.
"capabilities": [
"db",
"sync",
"printer",
"usb:read"
],
"kiosk": {
"cursor": false,
"blankAfter": 0
},
// device | installation | account | none
"bind": "installation"
}
usb:read rather than usb if you only enumerate devices, and drop anything you stop using.
Write the application
This is ordinary front-end code. The only ArdaForm-specific part is the arda global, which the runtime injects before your entry script runs.
// The runtime resolves this once the bridge is ready
const info = await arda.system.info()
document.querySelector('#device').textContent = info.deviceId
// A local store — survives reboots, encrypted at rest
const db = await arda.db('counter')
let count = (await db.get('total')) ?? 0
render()
document.querySelector('#add').addEventListener('click', async () => {
count++
await db.put('total', count)
// Durable — queued locally if the network is down
await arda.sync.push({ type: 'increment', count })
render()
})
// Degrade cleanly when a capability wasn't declared
if (arda.can('printer')) {
document.querySelector('#print').hidden = false
}
function render() {
document.querySelector('#count').textContent = count
}
Build a package
arda build runs your build command, bundles the output tree, signs it with your pack key and encrypts it. The result is a single file you could email if you wanted to — it's useless without a device authorised to open it.
$ arda build
build npm run build
bundling dist/ → 42 files, 1.84 MB
manifest caps: db, sync, printer, usb:read
signing ed25519 ✓
encrypting aes-256-gcm ✓
✓ app.arda sha256 4f9c…a10e
Your pack key signs locally. It is never uploaded and the control plane never holds it — see the security model.
Deploy to a device
arda push does the same build and uploads the result as an immutable release. arda deploy then points a target at it.
$ arda push -m "first build"
✓ release r-001 pushed to channel beta
$ arda devices
DEVICE GROUP RELEASE STATE SEEN
af-0c41d9 bench — online 2s
$ arda deploy r-001 --device af-0c41d9
af-0c41d9 downloading 1.84 MB
af-0c41d9 verifying sha256 ✓ signature ✓
af-0c41d9 staged restarting…
✓ 1 applied · 0 failed
Watch it run
Once it's live, the same terminal gets you inside the running page. This is the part that replaces driving to the site.
$ arda logs af-0c41d9 --follow
12:04:11 info app: ready in 612ms
12:04:19 info sync: queue drained (1 item)
$ arda console af-0c41d9
attached — evaluates in the live page
> await arda.system.info()
{ deviceId: 'af-0c41d9…', arch: 'amd64', uptimeSec: 8511 }
$ arda screenshot af-0c41d9 -o shot.png
✓ 1920x1080 png written to shot.png
Where next
- JavaScript API reference — every method your application can call.
- CLI reference — the full command surface, including staged rollouts and rollback.
- Package format — what's inside a
.ardafile and how binding works. - Deployment — provisioning hardware and running rollouts across a fleet.