# Get started


> From an empty folder to an app playing on a screen. What the manifest does, and why building one beats pointing a screen at a URL.
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

```text
my-app/
  index.html
  screenly.yml
  styles.css
  app.js
```

`index.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

```bash
screenly edge-app create "Throughput Board"
screenly edge-app validate
screenly edge-app run --generate-mock-data
screenly edge-app deploy
```

**Validate** catches a malformed manifest before anything reaches a screen. Run it first, always, and run it in [CI](/docs/developers/cli/guides/ci-pipelines/).

**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

```bash
screenly edge-app instance create
```

The app is the code; the **instance** is the code plus one configuration, and it is the instance that goes in a [playlist](/docs/playlists/). One app can have many, which is how the same board runs against three production lines. See [Instances](/docs/apps/using/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](/docs/apps/setting-up/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.

> [!IMPORTANT]
> 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](https://developer.screenly.io/edge-apps/).