diff --git a/.prettierignore b/.prettierignore
index 788b8769f..02058132e 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,4 +1,5 @@
**/*.min.js
+edge-apps/.bun-create/
edge-apps/edge-apps-library/
edge-apps/powerbi-legacy/
edge-apps/powerbi-legacy/**
diff --git a/edge-apps/.bun-create/edge-app-template/.gitignore b/edge-apps/.bun-create/edge-app-template/.gitignore
new file mode 100644
index 000000000..975f00c62
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/.gitignore
@@ -0,0 +1,6 @@
+node_modules/
+dist/
+*.log
+.DS_Store
+static/js/*.js
+static/js/*.js.map
diff --git a/edge-apps/.bun-create/edge-app-template/.ignore b/edge-apps/.bun-create/edge-app-template/.ignore
new file mode 100644
index 000000000..c2658d7d1
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/.ignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/edge-apps/.bun-create/edge-app-template/.prettierrc.json b/edge-apps/.bun-create/edge-app-template/.prettierrc.json
new file mode 100644
index 000000000..ea9f4ac6e
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/.prettierrc.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "https://json.schemastore.org/prettierrc",
+ "semi": false,
+ "singleQuote": true,
+ "printWidth": 80
+}
diff --git a/edge-apps/.bun-create/edge-app-template/README.md b/edge-apps/.bun-create/edge-app-template/README.md
new file mode 100644
index 000000000..79727c192
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/README.md
@@ -0,0 +1,41 @@
+# Simple Edge App Template
+
+A minimal starter template for building custom Screenly Edge Apps.
+
+## Features
+
+- Simple message display
+- Theme color integration via @screenly/edge-apps
+- Ready signal support
+- Minimal configuration
+
+## Deployment
+
+Create and deploy the Edge App:
+
+```bash
+screenly edge-app create --name my-app --in-place
+screenly edge-app deploy
+screenly edge-app instance create
+```
+
+## Configuration
+
+The app accepts the following settings via `screenly.yml`:
+
+- `message` - The message to display on screen
+
+## Development
+
+```bash
+bun install # Install dependencies
+bun run build # Build the app
+bun test # Run tests
+bun run dev # Start development server
+```
+
+## Testing
+
+```bash
+bun test
+```
diff --git a/edge-apps/.bun-create/edge-app-template/index.html b/edge-apps/.bun-create/edge-app-template/index.html
new file mode 100644
index 000000000..c53a62d34
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/index.html
@@ -0,0 +1,18 @@
+
+
+
+
+
+ Screenly Edge App
+
+
+
+
+
+
+
+
diff --git a/edge-apps/.bun-create/edge-app-template/package.json b/edge-apps/.bun-create/edge-app-template/package.json
new file mode 100644
index 000000000..0cfb5cb10
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "qr-code",
+ "version": "1.0.0",
+ "type": "module",
+ "scripts": {
+ "generate-mock-data": "screenly edge-app run --generate-mock-data",
+ "predev": "bun run generate-mock-data",
+ "dev": "run-p build:dev edge-app-server",
+ "edge-app-server": "screenly edge-app run",
+ "build": "bun run build:prod",
+ "build:dev": "bun build src/main.ts --outdir static/js --target browser --watch",
+ "build:prod": "bun build src/main.ts --outdir static/js --target browser",
+ "test": "bun test",
+ "test:unit": "bun test",
+ "lint": "tsc --noEmit",
+ "format-common": "prettier src/ README.md index.html",
+ "format": "bun run format-common --write",
+ "format:check": "bun run format-common --check",
+ "deploy": "bun run build && screenly edge-app deploy",
+ "prepare": "cd ../edge-apps-library && bun install && bun run build"
+ },
+ "dependencies": {
+ "qrcode": "^1.5.4"
+ },
+ "devDependencies": {
+ "@screenly/edge-apps": "workspace:../edge-apps-library",
+ "@types/bun": "^1.3.4",
+ "@types/jsdom": "^27.0.0",
+ "@types/qrcode": "^1.5.6",
+ "bun-types": "^1.3.5",
+ "jsdom": "^27.3.0",
+ "npm-run-all2": "^8.0.4",
+ "prettier": "^3.7.4",
+ "typescript": "^5.9.3"
+ }
+}
diff --git a/edge-apps/.bun-create/edge-app-template/screenly.yml b/edge-apps/.bun-create/edge-app-template/screenly.yml
new file mode 100644
index 000000000..cb593f48e
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/screenly.yml
@@ -0,0 +1,16 @@
+---
+syntax: manifest_v1
+description: A simple app that displays a customizable message.
+author: Screenly, Inc.
+ready_signal: true
+settings:
+ message:
+ type: string
+ default_value: 'Hello, world!'
+ title: Message
+ optional: false
+ help_text:
+ properties:
+ help_text: Enter the message to display.
+ type: string
+ schema_version: 1
diff --git a/edge-apps/.bun-create/edge-app-template/src/main.test.ts b/edge-apps/.bun-create/edge-app-template/src/main.test.ts
new file mode 100644
index 000000000..ed40c6060
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/src/main.test.ts
@@ -0,0 +1,17 @@
+import { describe, test, expect, beforeEach, afterEach } from 'bun:test'
+import { setupScreenlyMock, resetScreenlyMock } from '@screenly/edge-apps/test'
+
+describe('Simple Edge App', () => {
+ beforeEach(() => {
+ setupScreenlyMock({}, { message: 'Hello, world!' })
+ })
+
+ afterEach(() => {
+ resetScreenlyMock()
+ })
+
+ test('should display the message from settings', () => {
+ const message = screenly.settings.message as string
+ expect(message).toBe('Hello, world!')
+ })
+})
diff --git a/edge-apps/.bun-create/edge-app-template/src/main.ts b/edge-apps/.bun-create/edge-app-template/src/main.ts
new file mode 100644
index 000000000..55f255405
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/src/main.ts
@@ -0,0 +1,18 @@
+import { setupTheme, getSetting, signalReady } from '@screenly/edge-apps'
+
+window.onload = function () {
+ const message = getSetting('message') || 'Hello, world!'
+
+ // Setup branding colors using the library
+ setupTheme()
+
+ // Set the message
+ const messageElement =
+ document.querySelector('#message')
+ if (messageElement) {
+ messageElement.textContent = message
+ }
+
+ // Signal that the app is ready using the library
+ signalReady()
+}
diff --git a/edge-apps/.bun-create/edge-app-template/static/css/style.css b/edge-apps/.bun-create/edge-app-template/static/css/style.css
new file mode 100644
index 000000000..16a0d8c16
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/static/css/style.css
@@ -0,0 +1,84 @@
+/* Reset and base styles */
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+html {
+ font-size: 14px;
+}
+
+body {
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+ height: 100vh;
+ width: 100vw;
+ overflow: hidden;
+ background-color: var(--theme-color-background, #c9cdd0);
+}
+
+/* CSS Custom Properties */
+:root {
+ --theme-color-primary: #972eff;
+ --theme-color-tertiary: #ffffff;
+ --theme-color-background: #c9cdd0;
+}
+
+/* Main container */
+.container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+ width: 100%;
+ padding: 2rem;
+}
+
+/* Message section card */
+.message-section {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ height: 100%;
+ padding: clamp(1.5rem, 5vw, 24rem);
+ background: var(--theme-color-primary);
+ border-radius: 3.5rem;
+ color: var(--theme-color-tertiary);
+ box-shadow: 0 2.5rem 5rem rgba(0, 0, 0, 0.25), 0 1rem 2rem rgba(0, 0, 0, 0.15);
+ position: relative;
+ overflow: hidden;
+}
+
+/* Subtle background pattern */
+.message-section::before {
+ content: '';
+ position: absolute;
+ top: -50%;
+ right: -10%;
+ width: 40rem;
+ height: 40rem;
+ background: radial-gradient(circle, rgba(255, 255, 255, 0.08) 0%, transparent 70%);
+ border-radius: 50%;
+ pointer-events: none;
+}
+
+/* Message text */
+#message {
+ font-size: clamp(1.5rem, 6vw, 12rem);
+ font-weight: 700;
+ line-height: 1.3;
+ margin: 0;
+ letter-spacing: -0.01em;
+ text-shadow: 0 0.25rem 1rem rgba(0, 0, 0, 0.1);
+ position: relative;
+ z-index: 1;
+ text-align: center;
+}
+
+@media screen and (orientation: portrait) {
+ #message {
+ font-size: clamp(1.5rem, 8vh, 12rem);
+ }
+}
+
diff --git a/edge-apps/.bun-create/edge-app-template/tsconfig.json b/edge-apps/.bun-create/edge-app-template/tsconfig.json
new file mode 100644
index 000000000..b96c643dd
--- /dev/null
+++ b/edge-apps/.bun-create/edge-app-template/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "compilerOptions": {
+ "target": "ES2020",
+ "module": "ESNext",
+ "lib": ["ES2020", "DOM"],
+ "moduleResolution": "bundler",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "types": ["bun-types"]
+ },
+ "include": ["src/**/*.ts"],
+ "exclude": ["node_modules"]
+}
+