An edge app is a web page plus a manifest. The manifest is what turns it from a page into something a colleague can configure without touching your code.
What you are building
my-app/
index.html
screenly.yml
styles.css
app.jsindex.html is an ordinary page. screenly.yml declares the app’s name and the settings it needs, and the dashboard renders a form from it.
The loop
screenly edge-app create "Throughput Board"
screenly edge-app validate
screenly edge-app run --generate-mock-data
screenly edge-app deployValidate catches a malformed manifest before anything reaches a screen. Run it first, always, and run it in CI.
Run starts the app locally against generated mock data, so you develop without a device and without touching your workspace.
Deploy ships it. Every screen running the app picks up the new version on its next sync.
Then create an instance
screenly edge-app instance createThe app is the code; the instance is the code plus one configuration, and it is the instance that goes in a playlist. One app can have many, which is how the same board runs against three production lines. See Instances.
Designing the settings form
This is the part worth more thought than the code.
Order matters and you control it. Settings appear in the order your manifest declares them, so put what somebody must fill in first.
Hide what is irrelevant. depends_on makes a setting appear only once a prior choice makes it relevant. A form with eight fields where three do not apply is a form people get wrong.
Anything sensitive is a secret, not a setting. Settings are visible to anyone with workspace access. Secrets are encrypted, write-only once saved, and decrypted only on the device that owns the instance. See Settings and secrets.
Why bother, rather than a URL
If none of these apply, point a screen at your page and stop reading. That is a legitimate answer.
Configuration in the dashboard, so a non-technical colleague sets it up.
Secrets, so an API key never appears in the page source.
Versioned deploys, so one command updates the whole fleet.
A CORS proxy, so the app can fetch from APIs that would block a browser request, with no proxy of your own.
Branding, so it picks up your workspace logo and colors instead of having them hard-coded.
Test on what you are targeting
On a Screenly player or Player Max the app runs on the device. On some Screenly Anywhere platforms it is rendered on our infrastructure and sent as an image.
An app that animates or reacts between refreshes will not behave the same on Screenly Anywhere. Develop dynamic apps against the local emulator or a real player.
The full reference
The manifest schema, the JavaScript API, and the branding values are at developer.screenly.io.