@tomorrowos/sdk 0.7.7 → 0.7.9

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
@@ -2,6 +2,8 @@
2
2
 
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
+ >
6
+ > **On Replit, this file is the ONLY questionnaire.**
5
7
 
6
8
  ## User trigger (copy-paste)
7
9
 
@@ -9,7 +11,8 @@ When a human pastes a prompt like this, **read this file and start Question 1 im
9
11
 
10
12
  ```text
11
13
  Follow @tomorrowos/sdk REPLIT_SETUP.md and set up my TomorrowOS CMS.
12
- Ask me the questions in order. Do not skip steps.
14
+ Ask only the questions listed in REPLIT_SETUP.md, in order. Do not use LLM_PROMPT.md.
15
+ Do not skip steps.
13
16
  ```
14
17
 
15
18
  Alternate triggers that also activate this protocol:
@@ -17,20 +20,147 @@ Alternate triggers that also activate this protocol:
17
20
  - “Set up TomorrowOS on Replit using REPLIT_SETUP.md”
18
21
  - “Configure my TomorrowOS CMS (Replit wizard)”
19
22
 
23
+ When any of these triggers fire, **ignore `LLM_PROMPT.md` entirely** for the Q&A phase.
24
+
25
+ **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.
26
+
27
+ ---
28
+
29
+ ## Questionnaire scope (STRICT — read before asking anything)
30
+
31
+ Replit Agent must ask **only** the questions defined in **this file**, in **this exact order**:
32
+
33
+ | Step | Section | When |
34
+ |------|---------|------|
35
+ | 1 | **Question 1** — How many screens / devices? | Always |
36
+ | 2 | **Question 2** — Supabase connection | Only if answer to Q1 is **> 5** |
37
+ | 3 | **Question 3** — Media storage (Cloudinary vs Object Storage) | Always (after Q1 or Q2) |
38
+ | 4 | **Question 4** — Brand / TomorrowOS app look | Always last, before execution |
39
+
40
+ **That is the complete list.** There are no other setup questions.
41
+
42
+
43
+ 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.
44
+
45
+ If the user says “just set it up, don’t ask questions,” respond:
46
+
47
+ > I need four quick answers from REPLIT_SETUP.md (screen count, media storage, and branding). It takes about a minute and ensures the CMS deploys correctly on Replit.
48
+
49
+ Then ask **Question 1** — do not switch to `LLM_PROMPT.md`.
50
+
20
51
  ---
21
52
 
22
53
  ## Hard rules
23
54
 
24
- 1. **One question at a time.** Wait for the user’s answer before asking the next question (unless they already answered several in one message).
25
- 2. **Do not invent** screen counts, Cloudinary credentials, Supabase URLs, or brand colours.
26
- 3. **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.
27
- 4. **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.
28
- 5. **Never commit secrets** into git. Put credentials only in Replit **Secrets** (and optionally mirror non-secret flags in `.env` that reference env vars).
29
- 6. After Q&A, apply configuration, install deps, start the server, and verify:
55
+ 1. **Ask only REPLIT_SETUP.md questions 1–4** (see **Questionnaire scope**). Never use `LLM_PROMPT.md` on Replit.
56
+ 2. **One question at a time.** Wait for the user’s answer before asking the next question (unless they already answered several in one message).
57
+ 3. **Do not invent** screen counts, Cloudinary credentials, Supabase URLs, or brand colours.
58
+ 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.
59
+ 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.
60
+ 6. **Never commit secrets** into git. Put credentials only in Replit **Secrets** (and optionally mirror non-secret flags in `.env` that reference env vars).
61
+ 7. After Q&A, apply configuration, install deps, start the server, and verify:
30
62
  - HTTP Control Panel loads
31
63
  - `GET /brand.json` returns 200
32
64
  - WebSocket upgrade on `wss://<repl-host>/` succeeds (critical for TV pairing)
33
- 7. **Follow the Runtime & Replit publish rules below exactly.** A project that cannot Deploy / Publish on Replit is incomplete.
65
+ 8. **Follow the Runtime & Replit publish rules below exactly.** A project that cannot Deploy / Publish on Replit is incomplete.
66
+
67
+ **Question order after Q1:**
68
+
69
+ - If **≤ 5 screens:** Q1 → Q3 → Q4 → execution checklist
70
+ - If **> 5 screens:** Q1 → Q2 → Q3 → Q4 → execution checklist
71
+
72
+ Never insert extra questions between these steps.
73
+
74
+ ---
75
+
76
+ ## Deployability: Web app artifact (mandatory — fixes “api-kind not deployable”)
77
+
78
+ 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.
79
+
80
+ ### Create the project correctly (do this first)
81
+
82
+ When scaffolding a **new** Repl:
83
+
84
+ 1. On the Replit homepage, open the artifact-type dropdown and choose **Web app** (not API, not “Backend only”, not Agent & Automation-only).
85
+ 2. **Do not** create an “API server” artifact as the only publishable output.
86
+ 3. Describe the project as: *“TomorrowOS digital signage CMS — web Control Panel at `/` with WebSocket device pairing.”*
87
+ 4. Run `npx @tomorrowos/sdk init` at the project root (or merge the cms-starter template).
88
+
89
+ **Forbidden setups that cause publish failure:**
90
+
91
+ - ❌ Project / primary artifact classified as **API** (`api-kind` artifact)
92
+ - ❌ Backend-only Express/Fastify service with **no** `staticRoot` / Control Panel at `/`
93
+ - ❌ Splitting CMS into a non-publishable API artifact + separate unpublished frontend
94
+ - ❌ **Static Deployment** as the publish type (TomorrowOS needs a **live Node server** for WebSocket)
95
+ - ❌ `deploymentTarget` or publish mode that only serves static files without `tsx server.ts`
96
+
97
+ ### What “deployable” means for TomorrowOS
98
+
99
+ Replit Publish must see:
100
+
101
+ - A **Web app** that serves HTML at `GET /` (`public/index.html`)
102
+ - A Node process started by `npm run start` → `tsx server.ts`
103
+ - `host: "0.0.0.0"` and `port: Number(process.env.PORT) || 3000`
104
+ - An exposed port with `externalPort = 80` in `.replit` (see template below)
105
+ - **Autoscale** (or Reserved VM) deployment — **not** Static-only
106
+
107
+ ### `.replit` (create or replace — required for publish)
108
+
109
+ Use this **minimum** configuration (merge with existing Nix/modules if needed; **do not** remove `[[ports]]` or `deploymentTarget`):
110
+
111
+ ```toml
112
+ entrypoint = "server.ts"
113
+ modules = ["nodejs-20"]
114
+ hidden = [".config", "package-lock.json"]
115
+ run = "npm run start"
116
+
117
+ [nix]
118
+ channel = "stable-24_11"
119
+
120
+ [[ports]]
121
+ localPort = 3000
122
+ externalPort = 80
123
+
124
+ [deployment]
125
+ run = ["sh", "-c", "npm run start"]
126
+ deploymentTarget = "autoscale"
127
+ ignorePorts = false
128
+ ```
129
+
130
+ **Agent rules for `.replit`:**
131
+
132
+ - Set `entrypoint = "server.ts"` (not `index.js` unless that file exists and starts TomorrowOS).
133
+ - Set `deploymentTarget = "autoscale"` (WebSocket + long-lived connections; Static Deploy is wrong).
134
+ - Keep exactly **one** primary `[[ports]]` entry with `externalPort = 80` for the CMS server.
135
+ - 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.
136
+
137
+ 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`.
138
+
139
+ ### Publishing pane (human + Agent)
140
+
141
+ Before Publish:
142
+
143
+ 1. Confirm project filter / type shows **Web** (not API-only).
144
+ 2. In Publishing, choose **Autoscale** (recommended) or **Reserved VM** — **not Static**.
145
+ 3. Stop stale processes; clear port conflicts; restart workspace if needed.
146
+ 4. `npm run start` → Preview at `/` shows Control Panel.
147
+
148
+ After Publish, the public URL is:
149
+
150
+ `https://YOUR-REPLIT-DOMAIN`
151
+
152
+ ### If Publish says “api-kind artifact … not deployable”
153
+
154
+ **Do not** keep retrying publish unchanged. Fix in this order:
155
+
156
+ 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).
157
+ 2. Replace `.replit` with the template above (`entrypoint`, `modules`, `[[ports]]`, `deploymentTarget = "autoscale"`).
158
+ 3. Confirm `server.ts` calls `tomorrowos.listen({ staticRoot: join(__dirname, "public"), host: "0.0.0.0", port: Number(process.env.PORT) || 3000 })`.
159
+ 4. Confirm `GET /` returns Control Panel HTML (not JSON-only API root).
160
+ 5. In Publishing, switch to **Autoscale** if currently Static.
161
+ 6. Restart workspace → `npm run start` → Publish again.
162
+
163
+ Tell the user plainly if step 1 requires a new Repl — API-only projects cannot publish a browser CMS without reclassification.
34
164
 
35
165
  ---
36
166
 
@@ -70,7 +200,7 @@ Allowed extras (optional): `"build-player": "tomorrowos build --platform tizen"`
70
200
  "node": ">=20"
71
201
  },
72
202
  "dependencies": {
73
- "@tomorrowos/sdk": "^0.7.7",
203
+ "@tomorrowos/sdk": "^0.7.9",
74
204
  "dotenv": "^17.2.3",
75
205
  "tsx": "^4.19.0"
76
206
  },
@@ -101,28 +231,40 @@ npm run start
101
231
 
102
232
  ### `.replit` (create or edit)
103
233
 
234
+ Use the full template in **Deployability: Web app artifact** (not run/deployment lines only). Minimum:
235
+
104
236
  ```toml
237
+ entrypoint = "server.ts"
238
+ modules = ["nodejs-20"]
105
239
  run = "npm run start"
106
240
 
241
+ [[ports]]
242
+ localPort = 3000
243
+ externalPort = 80
244
+
107
245
  [deployment]
108
246
  run = ["sh", "-c", "npm run start"]
247
+ deploymentTarget = "autoscale"
248
+ ignorePorts = false
109
249
  ```
110
250
 
111
- 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`.
251
+ 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.
112
252
 
113
253
  ### Publish readiness checklist (before telling the user “done”)
114
254
 
115
- 1. Replit project type is **Web** (not API)
116
- 2. `package.json` has `scripts.start` = `tsx server.ts`
117
- 3. `tsx` is listed under `dependencies` (runtime-safe for Deploy)
118
- 4. Dependency is `@tomorrowos/sdk` (not a fork or vendored rewrite)
119
- 5. `.replit` Run + `[deployment].run` use `npm run start`
120
- 6. Node is **20+**
121
- 7. Preview at `/` shows the TomorrowOS Control Panel (not Canvas, not another app)
122
- 8. Stale processes / port conflicts cleared before publish
123
- 9. `npm run start` prints `[TomorrowOS] listening on http://0.0.0.0:...`
124
- 10. Browser WebSocket test to `wss://<host>/` succeeds
125
- 11. Secrets required by the Q&A answers are set (`SUPABASE_URL`, Cloudinary, etc.)
255
+ 1. Replit project / primary artifact is **Web app** (not API-only / `api-kind`)
256
+ 2. `.replit` has `entrypoint = "server.ts"`, `modules = ["nodejs-20"]`, `[[ports]]` with `externalPort = 80`, `deploymentTarget = "autoscale"`
257
+ 3. Publishing type is **Autoscale** or **Reserved VM** (not Static-only)
258
+ 4. `package.json` has `scripts.start` = `tsx server.ts`
259
+ 5. `tsx` is listed under `dependencies` (runtime-safe for Deploy)
260
+ 6. Dependency is `@tomorrowos/sdk` (not a fork or vendored rewrite)
261
+ 7. `.replit` Run + `[deployment].run` use `npm run start`
262
+ 8. Node is **20+**
263
+ 9. Preview at `/` shows the TomorrowOS Control Panel (not Canvas, not another app, not API JSON)
264
+ 10. Stale processes / port conflicts cleared before publish
265
+ 11. `npm run start` prints `[TomorrowOS] listening on http://0.0.0.0:...`
266
+ 12. Browser WebSocket test to `wss://<host>/` succeeds
267
+ 13. Secrets required by the Q&A answers are set (`SUPABASE_URL`, Cloudinary, etc.)
126
268
 
127
269
  If any item fails, fix it before finishing.
128
270
 
@@ -168,7 +310,9 @@ Verify after publish:
168
310
 
169
311
  ## Question 1 — How many screens / devices?
170
312
 
171
- **Ask exactly:**
313
+ > **This is the first and only “screen count” question.** Do not re-ask later.
314
+
315
+ **Ask exactly (copy wording; do not substitute LLM_PROMPT questions):**
172
316
 
173
317
  > How many TomorrowOS screens (devices) do you expect to manage with this CMS?
174
318
  >
@@ -288,7 +432,9 @@ Tell the user:
288
432
 
289
433
  ## Question 4 — Brand / TomorrowOS app look
290
434
 
291
- **Ask exactly:**
435
+ > **This is the only branding / platform / use-case question block.** Do not ask separate LLM_PROMPT “target platform”, “use case”, or “hosting” questions before this.
436
+
437
+ **Ask exactly (one message; user may answer in one reply):**
292
438
 
293
439
  > Let’s brand your TomorrowOS experience. Please provide:
294
440
  >
@@ -299,8 +445,7 @@ Tell the user:
299
445
  > 5. **Text colour** (hex, optional — default `#0A0908`)
300
446
  > 6. **Secondary / accent colour** (hex, optional)
301
447
  > 7. **Logo** — upload an SVG/PNG into the project, or give a URL I can fetch into `./assets/`
302
- > 8. **Target platforms** — `tizen`, `brightsign`, or both
303
- > 9. **Use case** — one of: `restaurant`, `retail`, `corporate`, `wayfinding`, `transit`, `other`
448
+
304
449
 
305
450
  If the user only gives a name and primary colour, use defaults for the rest and say what you assumed.
306
451
 
@@ -332,7 +477,7 @@ If the user only gives a name and primary colour, use defaults for the rest and
332
477
  }
333
478
  ```
334
479
 
335
- Set `cms.expectedScreens` from Question 1. Set `cmsEndpoint` only if the user already knows their public `wss://…replit.app` URL; otherwise leave it out and tell them to pair TVs using the published HTTPS URL (player converts `https://` → `wss://`).
480
+ Set `cms.expectedScreens` from Question 1 (do not ask screen count again). Always set `cms.hostingTarget` to `"here"` on Replit without asking. Set `cmsEndpoint` only if the user already knows their public `wss://…replit.app` URL; otherwise leave it out and tell them to pair TVs using the published HTTPS URL (player converts `https://` → `wss://`).
336
481
 
337
482
  ---
338
483
 
@@ -340,7 +485,9 @@ Set `cms.expectedScreens` from Question 1. Set `cmsEndpoint` only if the user al
340
485
 
341
486
  Run these steps in order. Tick mentally; do not skip.
342
487
 
343
- ### A. Seed the project
488
+ ### A. Seed the project (Web app first)
489
+
490
+ **If creating a new Repl:** choose **Web app** on the Replit homepage before `init`.
344
491
 
345
492
  ```bash
346
493
  npx @tomorrowos/sdk@latest init .
@@ -395,14 +542,7 @@ CLOUDINARY_API_SECRET=...
395
542
 
396
543
  2. Move / keep `tsx` in **`dependencies`** so Deploy works.
397
544
  3. Set `engines.node` to `>=20`.
398
- 4. Create or update `.replit`:
399
-
400
- ```toml
401
- run = "npm run start"
402
-
403
- [deployment]
404
- run = ["sh", "-c", "npm run start"]
405
- ```
545
+ 4. Create or update `.replit` using the **Deployability** template (`entrypoint`, `modules`, `[[ports]]`, `deploymentTarget = "autoscale"`).
406
546
 
407
547
  ### E. Install and run
408
548
 
@@ -453,6 +593,11 @@ If WebSocket fails, fix Run command / process crash / sleep **before** asking th
453
593
 
454
594
  ## What not to ask / change
455
595
 
596
+ ### Forbidden questionnaire sources
597
+
598
+ - **`LLM_PROMPT.md`** — not used on Replit setup; its five questions are **replaced** by REPLIT_SETUP Questions 1–4
599
+ - Standalone “target platform” / “hosting target” / “use case” prompts outside Question 4
600
+
456
601
  Do **not** ask the user how to implement:
457
602
 
458
603
  - WebSocket framing
@@ -470,6 +615,8 @@ Do **not**:
470
615
  - Leave `tsx` only in `devDependencies` if the Deploy pipeline installs production deps only
471
616
  - Use Canvas preview as the primary CMS verification surface
472
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
473
620
 
474
621
  ---
475
622
 
@@ -495,7 +642,8 @@ TOMORROWOS_STORE=sqlite
495
642
 
496
643
  | Symptom | Likely cause | Fix |
497
644
  |---------|--------------|-----|
498
- | 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 |
645
+ | 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 `/` |
646
+ | 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 |
499
647
  | TV / browser: WebSocket handshake timeout | Node CMS not running or crash-loop | Fix Run → `npm run start`; check logs for `listening` |
500
648
  | Deploy/Publish fails / `tsx: not found` | `tsx` only in devDependencies | Move `tsx` to `dependencies`, reinstall, keep `start`: `tsx server.ts` |
501
649
  | Deploy runs wrong process | `.replit` / Deployment not `npm run start` | Set `run = "npm run start"` and `[deployment] run = ["sh", "-c", "npm run start"]` |
@@ -509,4 +657,6 @@ TOMORROWOS_STORE=sqlite
509
657
 
510
658
  ## Protocol version
511
659
 
512
- `replit-setup/1.0` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
660
+ `replit-setup/1.2` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
661
+
662
+ **Changelog 1.2:** Web app deployability rules — avoid `api-kind` publish failure; full `.replit` with `[[ports]]`, `deploymentTarget = "autoscale"`, `entrypoint = "server.ts"`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "0.7.7",
3
+ "version": "0.7.9",
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.7",
3
+ "version": "0.7.9",
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.7",
16
+ "@tomorrowos/sdk": "^0.7.9",
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`** instead of this file. That protocol covers SQLite vs Supabase by screen count, `SUPABASE_URL`, Cloudinary vs Object Storage, and `brand.json`.
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.