The recommended way to create an Edge App
edge-apps/ directory.@screenly/edge-apps create-scaffold generator, following the kebab-case naming convention for the app name:
bunx @screenly/edge-apps create <app-name>
This produces a minimal, working app — manifest, index.html, src/main.ts, and the standard dev/build/lint/test/deploy scripts — already wired up to the library's conventions. Requires @screenly/edge-apps >=1.2.0..claude/), add and initialize the edge-apps-claude-config submodule for Claude AI configuration right after scaffolding, before or alongside making further code changes:
git submodule add https://github.com/Screenly/edge-apps-claude-config .claude
Teammates cloning the repo afterward need to populate it: git submodule update --init (or clone with --recurse-submodules).screenly_qc.yml (an internal-only staging manifest) — copy one over from a reference app if your app needs one, and keep both manifests in sync.bun run dev, bun run lint, and the tests. A scaffold that doesn't start is the first thing to fix.When the app shows data from a third-party service, do not hand-roll an auth flow — that is where things go wrong. Screenly delivers credentials through one runtime call, and your job is only to feed that call locally.
screenly.yml whose help_text.properties.type is oauth:<provider>:<field> (e.g. oauth:google_calendar:access_token). The field is either a credential or config the user picked (which calendar, which dashboard).const { token, metadata } = await getCredentials() // from @screenly/edge-apps
To develop locally (real credentials aren't present), set up a super simple way to supply them — pick the lighter of these two:
access_token secret marked "for testing only", set it with screenly edge-app setting set access_token=... (or in mock-data.yml), and read it with getSettingWithDefault('access_token', ''). See Screenly/google-calendar-app (src/main.ts).GET /access_token/ returning { token, metadata } — mimicking the Screenly OAuth service. Wire it in via mock-data.yml's screenly_oauth_tokens_url. See the mock-authenticator/ in Screenly/salesforce-app for a complete, minimal example.Both paths feed the same getCredentials() — the Edge App code does not change between them.
New Edge Apps should support optional Sentry error reporting, gated behind a sentry_dsn setting that no-ops when unset.
sentry_dsn setting to screenly.yml/screenly_qc.yml as a global secret that no-ops when unset:
settings:
sentry_dsn:
type: secret
title: Sentry DSN
optional: true
is_global: true
help_text:
schema_version: 1
properties:
advanced: true
help_text: Sentry DSN for reporting errors. Leave empty to disable.
type: string
setupSentry from @screenly/edge-apps/utils once, near the top of src/main.ts, before other startup logic, passing the app name and any settings or metadata useful as context:
setupSentry('app-name', { 'app-name': { screenName: screenly.metadata.screen_name } })
reportError(error, { source: 'short-context' }) from @screenly/edge-apps/utils at meaningful failure points (credential refresh, content load, API errors) — not for expected or already-handled states.@screenly/edge-apps ^1.1.0 or later.src/main.ts, src/credentials.ts) and Screenly/powerbi-app (src/main.ts, src/services.ts) for reference implementations.e2e/ directory (Playwright); add cases there for the behavior you build.bun run screenshots (builds the app and captures all Screenly resolutions). This is required — see edge-apps/CONTRIBUTING.md.screenly_qc.yml in sync with the app's settings and behavior.bun run lint and the tests pass.Most Edge Apps have migrated to standalone repos under the Screenly org. For reference on more complex implementations, consult:
All apps depend on the @screenly/edge-apps NPM package and use edge-apps-scripts for tooling.
categories key to reflect the app's purpose.settings key, sorted alphabetically.Screenly/cli repository.index.htmlREADME.mdSearch for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer