@tomorrowos/sdk 0.7.8 → 0.7.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/REPLIT_SETUP.md CHANGED
@@ -3,7 +3,7 @@
3
3
  > **This file is a contract for Replit Agent / Replit AI.**
4
4
  > Follow it literally. Ask questions in order. Do not invent answers. Do not write or rewrite application logic until the Q&A is complete. Prefer configuring Secrets, `.env`, `brand.json`, and `server.ts` store wiring over inventing a custom CMS.
5
5
  >
6
- > **On Replit, this file is the ONLY questionnaire.** Do **not** use `LLM_PROMPT.md` questions.
6
+ > **On Replit, this file is the ONLY questionnaire.**
7
7
 
8
8
  ## User trigger (copy-paste)
9
9
 
@@ -12,6 +12,7 @@ When a human pastes a prompt like this, **read this file and start Question 1 im
12
12
  ```text
13
13
  Follow @tomorrowos/sdk REPLIT_SETUP.md and set up my TomorrowOS CMS.
14
14
  Ask only the questions listed in REPLIT_SETUP.md, in order. Do not use LLM_PROMPT.md.
15
+ After the four answers, configure and start — minimal verification only (Web app type + Preview at /). No Supabase or WebSocket tests.
15
16
  Do not skip steps.
16
17
  ```
17
18
 
@@ -22,6 +23,8 @@ Alternate triggers that also activate this protocol:
22
23
 
23
24
  When any of these triggers fire, **ignore `LLM_PROMPT.md` entirely** for the Q&A phase.
24
25
 
26
+ **Before Question 1:** ensure the Replit workspace is a **Web app** project (see **Deployability: Web app artifact**). If the project is API-only or not publishable, fix that first — do not continue the questionnaire on a broken project type.
27
+
25
28
  ---
26
29
 
27
30
  ## Questionnaire scope (STRICT — read before asking anything)
@@ -37,18 +40,6 @@ Replit Agent must ask **only** the questions defined in **this file**, in **this
37
40
 
38
41
  **That is the complete list.** There are no other setup questions.
39
42
 
40
- ### Forbidden questions (never ask on Replit setup)
41
-
42
- Do **not** ask questions from `LLM_PROMPT.md` or improvise similar ones, including but not limited to:
43
-
44
- - ❌ “Which screen platform will you manage? … Tizen … BrightSign …” as a **standalone first question**
45
- - ❌ “What's the primary use case?” as a **standalone** question (use case is collected **inside Question 4** only)
46
- - ❌ “Where will the CMS server run? … here / vercel / railway …” — on Replit, hosting is always **`here`**; set `cms.hostingTarget: "here"` without asking
47
- - ❌ Separate “brand identity” interview before Question 4 (colours, logo, name belong in **Question 4** only)
48
- - ❌ “How many screens?” asked **again** after Question 1 (you already have `cms.expectedScreens`)
49
- - ❌ Any technical implementation question (WebSocket library, pairing format, etc.)
50
-
51
- **Target platform (`tizen` / `brightsign`):** collect only as **item 8 inside Question 4**, not as its own step.
52
43
 
53
44
  If the user volunteers extra info early (e.g. brand name before Q4), **record it** and still ask the current question’s required fields you do not yet have. Do not skip ahead to execution until Q1–Q4 (or Q1, Q3, Q4 if ≤5 screens) are complete.
54
45
 
@@ -68,10 +59,7 @@ Then ask **Question 1** — do not switch to `LLM_PROMPT.md`.
68
59
  4. **Do not use Replit’s reserved `DATABASE_URL` Secret for Supabase.** On Replit, `DATABASE_URL` is often pre-claimed. Always use **`SUPABASE_URL`** for TomorrowOS ↔ Supabase.
69
60
  5. **Prefer `npx @tomorrowos/sdk init`** (or the package’s `templates/cms-starter`) as the project seed. Do not rebuild pairing, WebSocket, or playlist APIs from scratch.
70
61
  6. **Never commit secrets** into git. Put credentials only in Replit **Secrets** (and optionally mirror non-secret flags in `.env` that reference env vars).
71
- 7. After Q&A, apply configuration, install deps, start the server, and verify:
72
- - HTTP Control Panel loads
73
- - `GET /brand.json` returns 200
74
- - WebSocket upgrade on `wss://<repl-host>/` succeeds (critical for TV pairing)
62
+ 7. After Q&A, **configure and start** do **not** run a long test suite (see **Post-Q&A: minimal verification only**).
75
63
  8. **Follow the Runtime & Replit publish rules below exactly.** A project that cannot Deploy / Publish on Replit is incomplete.
76
64
 
77
65
  **Question order after Q1:**
@@ -83,6 +71,97 @@ Never insert extra questions between these steps.
83
71
 
84
72
  ---
85
73
 
74
+ ## Deployability: Web app artifact (mandatory — fixes “api-kind not deployable”)
75
+
76
+ TomorrowOS CMS is a **user-facing Web app** (Control Panel at `/` + WebSocket for TVs). Replit must treat it as a **Web app** artifact, **not** an API-only / backend-library project.
77
+
78
+ ### Create the project correctly (do this first)
79
+
80
+ When scaffolding a **new** Repl:
81
+
82
+ 1. On the Replit homepage, open the artifact-type dropdown and choose **Web app** (not API, not “Backend only”, not Agent & Automation-only).
83
+ 2. **Do not** create an “API server” artifact as the only publishable output.
84
+ 3. Describe the project as: *“TomorrowOS digital signage CMS — web Control Panel at `/` with WebSocket device pairing.”*
85
+ 4. Run `npx @tomorrowos/sdk init` at the project root (or merge the cms-starter template).
86
+
87
+ **Forbidden setups that cause publish failure:**
88
+
89
+ - ❌ Project / primary artifact classified as **API** (`api-kind` artifact)
90
+ - ❌ Backend-only Express/Fastify service with **no** `staticRoot` / Control Panel at `/`
91
+ - ❌ Splitting CMS into a non-publishable API artifact + separate unpublished frontend
92
+ - ❌ **Static Deployment** as the publish type (TomorrowOS needs a **live Node server** for WebSocket)
93
+ - ❌ `deploymentTarget` or publish mode that only serves static files without `tsx server.ts`
94
+
95
+ ### What “deployable” means for TomorrowOS
96
+
97
+ Replit Publish must see:
98
+
99
+ - A **Web app** that serves HTML at `GET /` (`public/index.html`)
100
+ - A Node process started by `npm run start` → `tsx server.ts`
101
+ - `host: "0.0.0.0"` and `port: Number(process.env.PORT) || 3000`
102
+ - An exposed port with `externalPort = 80` in `.replit` (see template below)
103
+ - **Autoscale** (or Reserved VM) deployment — **not** Static-only
104
+
105
+ ### `.replit` (create or replace — required for publish)
106
+
107
+ Use this **minimum** configuration (merge with existing Nix/modules if needed; **do not** remove `[[ports]]` or `deploymentTarget`):
108
+
109
+ ```toml
110
+ entrypoint = "server.ts"
111
+ modules = ["nodejs-20"]
112
+ hidden = [".config", "package-lock.json"]
113
+ run = "npm run start"
114
+
115
+ [nix]
116
+ channel = "stable-24_11"
117
+
118
+ [[ports]]
119
+ localPort = 3000
120
+ externalPort = 80
121
+
122
+ [deployment]
123
+ run = ["sh", "-c", "npm run start"]
124
+ deploymentTarget = "autoscale"
125
+ ignorePorts = false
126
+ ```
127
+
128
+ **Agent rules for `.replit`:**
129
+
130
+ - Set `entrypoint = "server.ts"` (not `index.js` unless that file exists and starts TomorrowOS).
131
+ - Set `deploymentTarget = "autoscale"` (WebSocket + long-lived connections; Static Deploy is wrong).
132
+ - Keep exactly **one** primary `[[ports]]` entry with `externalPort = 80` for the CMS server.
133
+ - If `.replit` contains `[[artifacts]]` with **only** `artifacts/api-server` and Publish fails, **convert to Web app layout** or create a **new Web app** Repl and migrate — do not tell the user publish succeeded.
134
+
135
+ If Replit assigns a different `localPort` via `PORT`, update `localPort` to match the port in `[TomorrowOS] listening on http://0.0.0.0:<PORT>` logs, but keep `externalPort = 80`.
136
+
137
+ ### Publishing pane (human + Agent)
138
+
139
+ Before Publish:
140
+
141
+ 1. Confirm project filter / type shows **Web** (not API-only).
142
+ 2. In Publishing, choose **Autoscale** (recommended) or **Reserved VM** — **not Static**.
143
+ 3. Stop stale processes; clear port conflicts; restart workspace if needed.
144
+ 4. `npm run start` → Preview at `/` shows Control Panel.
145
+
146
+ After Publish, the public URL is:
147
+
148
+ `https://YOUR-REPLIT-DOMAIN`
149
+
150
+ ### If Publish says “api-kind artifact … not deployable”
151
+
152
+ **Do not** keep retrying publish unchanged. Fix in this order:
153
+
154
+ 1. Verify homepage artifact type is **Web app**; if the Repl was created as API-only, **create a new Web app Repl** and re-run this setup (fastest fix).
155
+ 2. Replace `.replit` with the template above (`entrypoint`, `modules`, `[[ports]]`, `deploymentTarget = "autoscale"`).
156
+ 3. Confirm `server.ts` calls `tomorrowos.listen({ staticRoot: join(__dirname, "public"), host: "0.0.0.0", port: Number(process.env.PORT) || 3000 })`.
157
+ 4. Confirm `GET /` returns Control Panel HTML (not JSON-only API root).
158
+ 5. In Publishing, switch to **Autoscale** if currently Static.
159
+ 6. Restart workspace → `npm run start` → Publish again.
160
+
161
+ Tell the user plainly if step 1 requires a new Repl — API-only projects cannot publish a browser CMS without reclassification.
162
+
163
+ ---
164
+
86
165
  ## Runtime & Replit publish rules (mandatory)
87
166
 
88
167
  These rules exist so the CMS can be **Run** and **Published/Deployed** on Replit without custom build steps.
@@ -119,7 +198,7 @@ Allowed extras (optional): `"build-player": "tomorrowos build --platform tizen"`
119
198
  "node": ">=20"
120
199
  },
121
200
  "dependencies": {
122
- "@tomorrowos/sdk": "^0.7.8",
201
+ "@tomorrowos/sdk": "^0.7.10",
123
202
  "dotenv": "^17.2.3",
124
203
  "tsx": "^4.19.0"
125
204
  },
@@ -150,30 +229,34 @@ npm run start
150
229
 
151
230
  ### `.replit` (create or edit)
152
231
 
232
+ Use the full template in **Deployability: Web app artifact** (not run/deployment lines only). Minimum:
233
+
153
234
  ```toml
235
+ entrypoint = "server.ts"
236
+ modules = ["nodejs-20"]
154
237
  run = "npm run start"
155
238
 
239
+ [[ports]]
240
+ localPort = 3000
241
+ externalPort = 80
242
+
156
243
  [deployment]
157
244
  run = ["sh", "-c", "npm run start"]
245
+ deploymentTarget = "autoscale"
246
+ ignorePorts = false
158
247
  ```
159
248
 
160
- If the workspace already has a `.replit`, **merge** these keys — do not wipe unrelated Nix/modules config. Ensure the effective Run and Deployment commands remain `npm run start`.
249
+ If the workspace already has a `.replit`, **merge** these keys — do not wipe unrelated Nix/modules config. Ensure Run, Deployment, **ports**, and **deploymentTarget** are correct.
161
250
 
162
251
  ### Publish readiness checklist (before telling the user “done”)
163
252
 
164
- 1. Replit project type is **Web** (not API)
165
- 2. `package.json` has `scripts.start` = `tsx server.ts`
166
- 3. `tsx` is listed under `dependencies` (runtime-safe for Deploy)
167
- 4. Dependency is `@tomorrowos/sdk` (not a fork or vendored rewrite)
168
- 5. `.replit` Run + `[deployment].run` use `npm run start`
169
- 6. Node is **20+**
170
- 7. Preview at `/` shows the TomorrowOS Control Panel (not Canvas, not another app)
171
- 8. Stale processes / port conflicts cleared before publish
172
- 9. `npm run start` prints `[TomorrowOS] listening on http://0.0.0.0:...`
173
- 10. Browser WebSocket test to `wss://<host>/` succeeds
174
- 11. Secrets required by the Q&A answers are set (`SUPABASE_URL`, Cloudinary, etc.)
253
+ **Only these three checks matter after setup.** Do not add more unless Publish fails.
175
254
 
176
- If any item fails, fix it before finishing.
255
+ 1. **Web app, not API** project / primary artifact is **Web app** (not `api-kind` / API-only).
256
+ 2. **`.replit` is correct** — `entrypoint = "server.ts"`, `modules = ["nodejs-20"]`, `[[ports]]` with `externalPort = 80`, `deploymentTarget = "autoscale"`, Run/Deploy = `npm run start`.
257
+ 3. **Preview at `/`** — after `npm run start`, logs show `[TomorrowOS] listening on http://0.0.0.0:...` and Preview shows the Control Panel (HTML), not empty / API JSON.
258
+
259
+ If all three pass, tell the user setup is complete. **Do not** block on extra tests below.
177
260
 
178
261
  ### Preview requirements (Replit workspace)
179
262
 
@@ -207,11 +290,37 @@ Tell the user their live CMS URLs:
207
290
 
208
291
  Replace `YOUR-REPLIT-DOMAIN` with the actual published hostname (e.g. `my-cms.replit.app`).
209
292
 
210
- Verify after publish:
293
+ **Do not** run post-publish smoke tests unless the user reports a problem. Telling them the URL is enough.
294
+
295
+ ---
296
+
297
+ ## Post-Q&A: minimal verification only
298
+
299
+ After Questions 1–4, **configure → `npm install` → `npm run start` → done.**
300
+
301
+ ### Do (maximum)
302
+
303
+ 1. Confirm **Web app** artifact (not API) — **most important**.
304
+ 2. Write Secrets / `.env` / `brand.json` / `server.ts` / `.replit` from answers.
305
+ 3. `npm install` && `npm run start`.
306
+ 4. Glance at logs for `[TomorrowOS] listening on http://0.0.0.0:...`.
307
+ 5. Glance at Preview — Control Panel visible at `/`.
308
+
309
+ ### Do NOT run after setup (unless user asks or Publish fails)
310
+
311
+ - ❌ **Supabase connection test** (no `psql`, no DB ping, no “testing Supabase connection…”)
312
+ - ❌ **Cloudinary upload test**
313
+ - ❌ **`curl` / `fetch` on `/brand.json`** as a formal gate
314
+ - ❌ **Browser WebSocket console snippet** as a formal gate
315
+ - ❌ **Publishing dry-run** unless the user asked to publish now
316
+ - ❌ **Long troubleshooting loops** when Preview already shows the Control Panel
317
+ - ❌ Re-running the full **Publish readiness checklist** item-by-item in chat
318
+
319
+ If Preview shows the Control Panel and the project is **Web app** type, **stop testing** and give the user their URL and next steps.
211
320
 
212
- 1. `https://YOUR-REPLIT-DOMAIN/` shows the Control Panel (not empty, not API docs).
213
- 2. `https://YOUR-REPLIT-DOMAIN/brand.json` returns 200.
214
- 3. WebSocket to `wss://YOUR-REPLIT-DOMAIN/` succeeds.
321
+ ### Only if Preview is empty or Publish fails
322
+
323
+ Then (and only then) check: API vs Web type → `.replit` ports/`deploymentTarget` → stale process / port conflict → see **Failure recovery cheat sheet**.
215
324
 
216
325
  ---
217
326
 
@@ -290,6 +399,7 @@ DATABASE_SSL=true
290
399
  ```
291
400
 
292
401
  5. **Do not** write the real password into committed files.
402
+ 6. **Do not** test the Supabase connection after saving the Secret — configuration only.
293
403
 
294
404
  If the user refuses Supabase but chose > 5 screens, warn them SQLite on Replit is fragile for fleets, then offer SQLite only after they confirm.
295
405
 
@@ -352,8 +462,7 @@ Tell the user:
352
462
  > 5. **Text colour** (hex, optional — default `#0A0908`)
353
463
  > 6. **Secondary / accent colour** (hex, optional)
354
464
  > 7. **Logo** — upload an SVG/PNG into the project, or give a URL I can fetch into `./assets/`
355
- > 8. **Target platforms** — `tizen`, `brightsign`, or both
356
- > 9. **Use case** — one of: `restaurant`, `retail`, `corporate`, `wayfinding`, `transit`, `other`
465
+
357
466
 
358
467
  If the user only gives a name and primary colour, use defaults for the rest and say what you assumed.
359
468
 
@@ -393,7 +502,9 @@ Set `cms.expectedScreens` from Question 1 (do not ask screen count again). Alway
393
502
 
394
503
  Run these steps in order. Tick mentally; do not skip.
395
504
 
396
- ### A. Seed the project
505
+ ### A. Seed the project (Web app first)
506
+
507
+ **If creating a new Repl:** choose **Web app** on the Replit homepage before `init`.
397
508
 
398
509
  ```bash
399
510
  npx @tomorrowos/sdk@latest init .
@@ -448,19 +559,10 @@ CLOUDINARY_API_SECRET=...
448
559
 
449
560
  2. Move / keep `tsx` in **`dependencies`** so Deploy works.
450
561
  3. Set `engines.node` to `>=20`.
451
- 4. Create or update `.replit`:
452
-
453
- ```toml
454
- run = "npm run start"
455
-
456
- [deployment]
457
- run = ["sh", "-c", "npm run start"]
458
- ```
562
+ 4. Create or update `.replit` using the **Deployability** template (`entrypoint`, `modules`, `[[ports]]`, `deploymentTarget = "autoscale"`).
459
563
 
460
564
  ### E. Install and run
461
565
 
462
- **Before starting:** stop stale processes, clear old background tasks, free the port if needed, restart workspace if stuck.
463
-
464
566
  ```bash
465
567
  npm install
466
568
  npm run start
@@ -468,30 +570,15 @@ npm run start
468
570
 
469
571
  (Use `npm run dev` only for local edit/watch. **Publish / Deploy / Replit Run must use `npm run start`.**)
470
572
 
471
- Confirm logs contain something like:
472
-
473
- ```text
474
- [TomorrowOS] listening on http://0.0.0.0:<PORT>
475
- ```
476
-
477
- Confirm the **Web preview** (not Canvas) shows the Control Panel at `/`.
573
+ **Minimal check:** logs contain `[TomorrowOS] listening on http://0.0.0.0:...` and Preview shows Control Panel at `/`. Then proceed to **G** — no further tests.
478
574
 
479
- ### F. Verify before telling the user “done”
575
+ ### F. Done skip extended verification
480
576
 
481
- 1. Replit project type is **Web**; preview at `/` shows Control Panel (not empty, not Canvas-only).
482
- 2. Open the Control Panel URL.
483
- 3. `GET /brand.json` → 200 and correct `name` / colours.
484
- 4. In browser console on the Control Panel origin:
485
-
486
- ```javascript
487
- const ws = new WebSocket(location.origin.replace(/^http/, "ws") + "/");
488
- ws.onopen = () => console.log("WS OK");
489
- ws.onerror = (e) => console.log("WS ERR", e);
490
- ```
577
+ If the **three-item Publish readiness checklist** passes (especially **Web app, not API**), mark setup complete.
491
578
 
492
- 5. Confirm the **Publish readiness checklist** in **Runtime & Replit publish rules**.
579
+ **Do not** run WebSocket console tests, Supabase connection tests, or `brand.json` curl checks here.
493
580
 
494
- If WebSocket fails, fix Run command / process crash / sleep **before** asking the user to pair a TV.
581
+ Only investigate further if Preview is empty, server crashed, or user reports Publish failure.
495
582
 
496
583
  ### G. Tell the user next steps (no code)
497
584
 
@@ -528,6 +615,9 @@ Do **not**:
528
615
  - Leave `tsx` only in `devDependencies` if the Deploy pipeline installs production deps only
529
616
  - Use Canvas preview as the primary CMS verification surface
530
617
  - Serve a different app or API-only response at `/` instead of the Control Panel
618
+ - Create the Repl as **API-only** or publish with **Static Deployment** only
619
+ - Omit `[[ports]]` / `deploymentTarget` from `.replit` when setting up for Publish
620
+ - Run **Supabase connection tests**, **WebSocket console tests**, or other post-setup smoke tests unless Preview fails or the user asks
531
621
 
532
622
  ---
533
623
 
@@ -553,7 +643,8 @@ TOMORROWOS_STORE=sqlite
553
643
 
554
644
  | Symptom | Likely cause | Fix |
555
645
  |---------|--------------|-----|
556
- | Preview empty / wrong app at `/` | Project type API, wrong staticRoot, or stale process | Set project to **Web**; confirm `staticRoot: public`; stop old servers; restart workspace |
646
+ | Publish: **api-kind artifact not deployable** | Repl created as API-only, or missing Web app + ports | New **Web app** Repl **or** fix `.replit` (`entrypoint`, `[[ports]]`, `deploymentTarget=autoscale`); serve Control Panel at `/` |
647
+ | Preview empty / wrong app at `/` | Project type API, wrong staticRoot, or stale process | Set project to **Web app**; confirm `staticRoot: public`; stop old servers; restart workspace |
557
648
  | TV / browser: WebSocket handshake timeout | Node CMS not running or crash-loop | Fix Run → `npm run start`; check logs for `listening` |
558
649
  | Deploy/Publish fails / `tsx: not found` | `tsx` only in devDependencies | Move `tsx` to `dependencies`, reinstall, keep `start`: `tsx server.ts` |
559
650
  | Deploy runs wrong process | `.replit` / Deployment not `npm run start` | Set `run = "npm run start"` and `[deployment] run = ["sh", "-c", "npm run start"]` |
@@ -567,6 +658,6 @@ TOMORROWOS_STORE=sqlite
567
658
 
568
659
  ## Protocol version
569
660
 
570
- `replit-setup/1.1` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
661
+ `replit-setup/1.3` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
571
662
 
572
- **Changelog 1.1:** strict questionnaire scope; Replit must not use `LLM_PROMPT.md` questions (e.g. standalone target-platform prompt).
663
+ **Changelog 1.3:** minimal post-Q&A verification no Supabase/WS smoke tests; prioritize **Web app vs API** only.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "0.7.8",
3
+ "version": "0.7.10",
4
4
  "description": "TomorrowOS CMS server SDK - WebSocket transport, pairing, device commands, optional static CMS UI. Includes CLI (tomorrowos init / build) and starter templates.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,4 +1,17 @@
1
+ entrypoint = "server.ts"
2
+ modules = ["nodejs-20"]
3
+ hidden = [".config", "package-lock.json"]
1
4
  run = "npm run start"
2
5
 
6
+ [nix]
7
+ channel = "stable-24_11"
8
+
9
+ # Expose the CMS HTTP + WebSocket server (TomorrowOS Control Panel at /).
10
+ [[ports]]
11
+ localPort = 3000
12
+ externalPort = 80
13
+
3
14
  [deployment]
4
15
  run = ["sh", "-c", "npm run start"]
16
+ deploymentTarget = "autoscale"
17
+ ignorePorts = false
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "0.7.8",
3
+ "version": "0.7.10",
4
4
  "description": "CMS server on @tomorrowos/sdk. Add your UI (React, static files, etc.) alongside this server.",
5
5
  "private": true,
6
6
  "type": "module",
@@ -13,7 +13,7 @@
13
13
  "build-player": "tomorrowos build --platform tizen"
14
14
  },
15
15
  "dependencies": {
16
- "@tomorrowos/sdk": "^0.7.8",
16
+ "@tomorrowos/sdk": "^0.7.10",
17
17
  "dotenv": "^17.2.3",
18
18
  "tsx": "^4.19.0"
19
19
  },
package/LLM_PROMPT.md DELETED
@@ -1,173 +0,0 @@
1
- # Elicitation Protocol for TomorrowOS CMS Projects
2
-
3
- > **This file is the contract between TomorrowOS and any LLM generating code using this package. You must follow it literally. Do not skip questions, do not infer answers, do not start writing code until the protocol is complete.**
4
-
5
- > **Replit Agent:** if the user is setting up a CMS on Replit (or pastes a prompt that mentions `REPLIT_SETUP.md`), follow **`REPLIT_SETUP.md` only** — not this file. Do **not** ask `LLM_PROMPT.md` questions (e.g. standalone “Which screen platform will you manage?”). Replit uses four questions: screen count → optional Supabase → media storage → brand (including platform and use case inside Question 4).
6
-
7
- You are generating a digital signage CMS using `@tomorrowos/sdk`. The user has asked you to build something like "a CMS for my restaurant" or "a signage dashboard for my retail network". Before you write any code, you must gather five pieces of information from the user.
8
-
9
- Ask each question in order. If the user answers multiple at once, record those and skip ahead. If the user hasn't given you an answer to a specific field, do not invent one — ask the question explicitly.
10
-
11
- ---
12
-
13
- ## Question 1 — Target platform
14
-
15
- **Ask exactly:**
16
-
17
- > "Which screen platform will you manage? TomorrowOS V1 fully supports Samsung Tizen (commercial signage displays) and BrightSign (media players). Which would you like to target?"
18
-
19
- **Valid answers:** `tizen`, `brightsign`, or `both`
20
-
21
- **If the user names a platform not in V1** (webOS, Android, ChromeOS, Windows), respond:
22
-
23
- > "That platform is planned for a later release. For V1, the supported options are Tizen and BrightSign. Which would you like to use for now?"
24
-
25
- **Store answer as:** `targetPlatforms` array in `brand.json`
26
-
27
- ---
28
-
29
- ## Question 2 — Brand identity
30
-
31
- **Ask exactly:**
32
-
33
- > "What's the name of the product or company this CMS is for? I'll also need:
34
- >
35
- > - A logo file (SVG preferred, PNG acceptable — or a URL I can fetch)
36
- > - A primary brand colour (hex format, e.g. `#FF8A3D`)
37
- > - Optional: a secondary/accent colour"
38
-
39
- **Required fields:**
40
-
41
- - `brand.name` — string
42
- - `brand.primaryColor` — hex string matching `^#[0-9A-Fa-f]{6}$`
43
- - `brand.logoPath` — relative path to logo file the user will save to the project
44
-
45
- **If the user does not provide a logo**, proceed with a placeholder comment in the generated code noting that the logo must be added before production use. Do not fabricate a logo.
46
-
47
- **If the user provides a brand name but no colour**, ask:
48
-
49
- > "What's the primary colour for your brand? I need it as a hex code like `#FF8A3D`."
50
-
51
- Store answers in `brand.json`.
52
-
53
- ---
54
-
55
- ## Question 3 — Use case
56
-
57
- **Ask exactly:**
58
-
59
- > "What's the primary use case for this CMS? For example: restaurant menu boards, retail promotions, corporate lobby displays, hospital wayfinding, transit information."
60
-
61
- **Use the answer to:**
62
-
63
- - Tailor the example content shown in the starter template (e.g. menu items vs retail promo templates)
64
- - Set the dashboard's default greeting and page titles
65
- - Suggest sensible default playlist names
66
-
67
- **Do NOT use the answer to:**
68
-
69
- - Change the SDK method signatures
70
- - Add or remove required components from `BUILD_GUARDRAILS.md`
71
- - Skip any mandatory pages
72
-
73
- The SDK contract is identical regardless of use case. Use case only affects content and copy.
74
-
75
- **Store answer as:** `cms.useCase` in `brand.json` (one of: `restaurant`, `retail`, `corporate`, `wayfinding`, `transit`, `other`)
76
-
77
- ---
78
-
79
- ## Question 4 — Hosting target
80
-
81
- **Ask exactly:**
82
-
83
- > "Where will the CMS server run? Options:
84
- >
85
- > - `here` — you're in Replit, Claude Code, or another hosted AI workspace (I'll configure it automatically)
86
- > - `vercel` — deploy to Vercel
87
- > - `railway` — deploy to Railway
88
- > - `self-hosted` — you'll run it on your own infrastructure"
89
-
90
- **If the user says `here`:**
91
-
92
- - Use environment variable `process.env.PORT` for the server port
93
- - Configure the WebSocket handler to bind to `0.0.0.0`
94
- - Include a comment in `server.ts` noting that Replit/Claude Code handles the hosting and HTTPS termination
95
- - Do NOT commit any secrets or keys to the generated code
96
-
97
- **If the user says `vercel`:**
98
-
99
- - Note that Vercel free tier has WebSocket limitations; recommend Railway for production
100
- - Generate `vercel.json` with appropriate WebSocket routing
101
-
102
- **If the user says `railway`:**
103
-
104
- - Generate `railway.toml` with port configuration
105
- - Include Dockerfile if appropriate
106
-
107
- **Store answer as:** `cms.hostingTarget` in `brand.json`
108
-
109
- ---
110
-
111
- ## Question 5 — Expected number of screens
112
-
113
- **Ask exactly:**
114
-
115
- > "How many screens will you manage initially? (1-10 is fine for testing. For larger deployments I'll add pagination and grouping features.)"
116
-
117
- **If answer is 1-10:** generate simple list views without pagination.
118
-
119
- **If answer is 11-100:** include pagination on the screens list page (page size 20).
120
-
121
- **If answer is 100+:** include pagination, grouping, and tag filtering on the screens list. Note to user that fleet-level features (bulk commands, group broadcast) are recommended.
122
-
123
- **Store answer as:** `cms.expectedScreens` in `brand.json`
124
-
125
- ---
126
-
127
- ## After all five answers collected
128
-
129
- Follow this sequence strictly:
130
-
131
- 1. **Write `brand.json`** at the project root using the answers. Validate against `brand.schema.json`.
132
- 2. **Run `npx tomorrowos init [dir]`** or copy `templates/cms-starter/` from the SDK package into the user's project as the seed.
133
- 3. **Customise the starter:**
134
- - Replace placeholder brand name, colour, logo references
135
- - Rename example content to match the use case
136
- - Remove any platform-specific notes for platforms the user didn't select
137
- 4. **Read `BUILD_GUARDRAILS.md`** and verify every mandatory component is present in the generated code. Do not skip any.
138
- 5. **Run `npm install`** and confirm dependencies resolve.
139
- 6. **Start the dev server** (`npm run dev`) and confirm it runs without errors.
140
- 7. **Show the user `PLAYER_INSTALL.md`** and explain what to do next to get a screen paired and controllable.
141
-
142
- ---
143
-
144
- ## What not to ask
145
-
146
- Do not ask the user:
147
-
148
- - How WebSocket connections should be handled (the SDK handles this)
149
- - How to implement pairing (the SDK handles this)
150
- - How to format command messages (the SDK handles this)
151
- - Which WebSocket library to use (the SDK bundles this)
152
- - What TCP port to use (use `process.env.PORT` or `3000`)
153
- - Whether to use TypeScript or JavaScript (default to TypeScript; offer JS only if user explicitly asks)
154
-
155
- These are implementation details the SDK controls. The user cares about their brand, their platform, their use case. Everything else is the SDK's job.
156
-
157
- ---
158
-
159
- ## When to re-prompt
160
-
161
- If the user's initial prompt already contains answers to some questions (e.g. "build me a CMS for my Acme Burger restaurant menu boards on Samsung Tizen"), record those answers and only ask the remaining questions. Do not re-ask what the user has already told you.
162
-
163
- If the user says "just build it, don't ask me questions," respond:
164
-
165
- > "I'd love to, but I need five quick answers to make sure the CMS you get actually works with your screens and looks like your brand. It'll take about sixty seconds. Ready?"
166
-
167
- Do not proceed without the answers. The SDK will not function without at minimum: `targetPlatforms`, `brand.name`, `brand.primaryColor`, and `cms.hostingTarget`.
168
-
169
- ---
170
-
171
- ## Protocol version
172
-
173
- This elicitation protocol is version `1.0`, aligned with TomorrowOS wire protocol `1.0`. Future SDK versions may add questions; they will not remove existing ones without a major-version bump.