@tomorrowos/sdk 0.7.6 → 0.7.8

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/LLM_PROMPT.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
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
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`.
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
6
 
7
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
8
 
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.** Do **not** use `LLM_PROMPT.md` questions.
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,66 @@ 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
+ ---
26
+
27
+ ## Questionnaire scope (STRICT — read before asking anything)
28
+
29
+ Replit Agent must ask **only** the questions defined in **this file**, in **this exact order**:
30
+
31
+ | Step | Section | When |
32
+ |------|---------|------|
33
+ | 1 | **Question 1** — How many screens / devices? | Always |
34
+ | 2 | **Question 2** — Supabase connection | Only if answer to Q1 is **> 5** |
35
+ | 3 | **Question 3** — Media storage (Cloudinary vs Object Storage) | Always (after Q1 or Q2) |
36
+ | 4 | **Question 4** — Brand / TomorrowOS app look | Always last, before execution |
37
+
38
+ **That is the complete list.** There are no other setup questions.
39
+
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
+
53
+ 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
+
55
+ If the user says “just set it up, don’t ask questions,” respond:
56
+
57
+ > 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.
58
+
59
+ Then ask **Question 1** — do not switch to `LLM_PROMPT.md`.
60
+
20
61
  ---
21
62
 
22
63
  ## Hard rules
23
64
 
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:
65
+ 1. **Ask only REPLIT_SETUP.md questions 1–4** (see **Questionnaire scope**). Never use `LLM_PROMPT.md` on Replit.
66
+ 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).
67
+ 3. **Do not invent** screen counts, Cloudinary credentials, Supabase URLs, or brand colours.
68
+ 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
+ 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
+ 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:
30
72
  - HTTP Control Panel loads
31
73
  - `GET /brand.json` returns 200
32
74
  - 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.
75
+ 8. **Follow the Runtime & Replit publish rules below exactly.** A project that cannot Deploy / Publish on Replit is incomplete.
76
+
77
+ **Question order after Q1:**
78
+
79
+ - If **≤ 5 screens:** Q1 → Q3 → Q4 → execution checklist
80
+ - If **> 5 screens:** Q1 → Q2 → Q3 → Q4 → execution checklist
81
+
82
+ Never insert extra questions between these steps.
34
83
 
35
84
  ---
36
85
 
@@ -70,7 +119,7 @@ Allowed extras (optional): `"build-player": "tomorrowos build --platform tizen"`
70
119
  "node": ">=20"
71
120
  },
72
121
  "dependencies": {
73
- "@tomorrowos/sdk": "^0.7.6",
122
+ "@tomorrowos/sdk": "^0.7.8",
74
123
  "dotenv": "^17.2.3",
75
124
  "tsx": "^4.19.0"
76
125
  },
@@ -112,22 +161,65 @@ If the workspace already has a `.replit`, **merge** these keys — do not wipe u
112
161
 
113
162
  ### Publish readiness checklist (before telling the user “done”)
114
163
 
115
- 1. `package.json` has `scripts.start` = `tsx server.ts`
116
- 2. `tsx` is listed under `dependencies` (runtime-safe for Deploy)
117
- 3. Dependency is `@tomorrowos/sdk` (not a fork or vendored rewrite)
118
- 4. `.replit` Run + `[deployment].run` use `npm run start`
119
- 5. Node is **20+**
120
- 6. `npm run start` prints `[TomorrowOS] listening on http://0.0.0.0:...`
121
- 7. Browser WebSocket test to `wss://<host>/` succeeds
122
- 8. Secrets required by the Q&A answers are set (`SUPABASE_URL`, Cloudinary, etc.)
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.)
123
175
 
124
176
  If any item fails, fix it before finishing.
125
177
 
178
+ ### Preview requirements (Replit workspace)
179
+
180
+ The Replit **Preview** must show the **TomorrowOS Control Panel** at `/` (root URL).
181
+
182
+ - `GET /` must serve the CMS Control Panel (`public/index.html` via `staticRoot: public`).
183
+ - **Do not** serve another app, API-only landing page, or placeholder at `/`.
184
+ - **Do not** use or rely on the **Canvas** preview for this CMS — use the normal **Web** preview in the browser.
185
+ - If the preview is **empty** or shows the wrong thing:
186
+ 1. Confirm the Replit project type is **Web**, not **API**.
187
+ 2. Confirm `npm run start` is running and logs show `[TomorrowOS] listening on http://0.0.0.0:...`
188
+ 3. Confirm `server.ts` calls `tomorrowos.listen({ staticRoot: join(__dirname, "public"), ... })`
189
+ 4. Open the preview URL directly (not Canvas) and hard-refresh.
190
+
191
+ ### Before publishing / deploying
192
+
193
+ Do this **before** clicking Publish / Deploy:
194
+
195
+ 1. **Stop** stale running processes (old `tsx` / `node` servers from prior attempts).
196
+ 2. **Clear** old background tasks from previous failed projects (Replit Shell / Processes panel).
197
+ 3. **Ensure no old process is holding the port** (`EADDRINUSE` in logs = something still bound to `PORT`).
198
+ 4. **Restart the Replit workspace** if the port is stuck or preview still shows a ghost app.
199
+ 5. Run `npm run start` once cleanly and confirm Control Panel loads at `/` in preview.
200
+
201
+ ### After publishing / deploying
202
+
203
+ Tell the user their live CMS URLs:
204
+
205
+ - **Control Panel (browser):** `https://YOUR-REPLIT-DOMAIN`
206
+ - **TV / player CMS endpoint:** same HTTPS origin, e.g. `https://YOUR-REPLIT-DOMAIN/` (player converts `https://` → `wss://` for WebSocket)
207
+
208
+ Replace `YOUR-REPLIT-DOMAIN` with the actual published hostname (e.g. `my-cms.replit.app`).
209
+
210
+ Verify after publish:
211
+
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.
215
+
126
216
  ---
127
217
 
128
218
  ## Question 1 — How many screens / devices?
129
219
 
130
- **Ask exactly:**
220
+ > **This is the first and only “screen count” question.** Do not re-ask later.
221
+
222
+ **Ask exactly (copy wording; do not substitute LLM_PROMPT questions):**
131
223
 
132
224
  > How many TomorrowOS screens (devices) do you expect to manage with this CMS?
133
225
  >
@@ -247,7 +339,9 @@ Tell the user:
247
339
 
248
340
  ## Question 4 — Brand / TomorrowOS app look
249
341
 
250
- **Ask exactly:**
342
+ > **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.
343
+
344
+ **Ask exactly (one message; user may answer in one reply):**
251
345
 
252
346
  > Let’s brand your TomorrowOS experience. Please provide:
253
347
  >
@@ -291,7 +385,7 @@ If the user only gives a name and primary colour, use defaults for the rest and
291
385
  }
292
386
  ```
293
387
 
294
- 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://`).
388
+ 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://`).
295
389
 
296
390
  ---
297
391
 
@@ -365,6 +459,8 @@ run = ["sh", "-c", "npm run start"]
365
459
 
366
460
  ### E. Install and run
367
461
 
462
+ **Before starting:** stop stale processes, clear old background tasks, free the port if needed, restart workspace if stuck.
463
+
368
464
  ```bash
369
465
  npm install
370
466
  npm run start
@@ -378,11 +474,14 @@ Confirm logs contain something like:
378
474
  [TomorrowOS] listening on http://0.0.0.0:<PORT>
379
475
  ```
380
476
 
477
+ Confirm the **Web preview** (not Canvas) shows the Control Panel at `/`.
478
+
381
479
  ### F. Verify before telling the user “done”
382
480
 
383
- 1. Open the Control Panel URL.
384
- 2. `GET /brand.json` 200 and correct `name` / colours.
385
- 3. In browser console on the Control Panel origin:
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:
386
485
 
387
486
  ```javascript
388
487
  const ws = new WebSocket(location.origin.replace(/^http/, "ws") + "/");
@@ -390,22 +489,28 @@ ws.onopen = () => console.log("WS OK");
390
489
  ws.onerror = (e) => console.log("WS ERR", e);
391
490
  ```
392
491
 
393
- 4. Confirm the **Publish readiness checklist** in **Runtime & Replit publish rules**.
492
+ 5. Confirm the **Publish readiness checklist** in **Runtime & Replit publish rules**.
394
493
 
395
494
  If WebSocket fails, fix Run command / process crash / sleep **before** asking the user to pair a TV.
396
495
 
397
496
  ### G. Tell the user next steps (no code)
398
497
 
399
498
  1. Keep this Repl **running** (Always On if available).
400
- 2. On the TomorrowOS player, enter the CMS URL: `https://<your-repl>.replit.app/`
401
- 3. Enter the 6-character pairing code from the screen into the Control Panel.
402
- 4. Create a playlist, upload media, Publish to the device.
403
- 5. Point them at `PLAYER_INSTALL.md` in the SDK for player install details.
499
+ 2. **Published Control Panel URL:** `https://YOUR-REPLIT-DOMAIN`
500
+ 3. On the TomorrowOS player, enter the CMS URL: `https://YOUR-REPLIT-DOMAIN/`
501
+ 4. Enter the 6-character pairing code from the screen into the Control Panel.
502
+ 5. Create a playlist, upload media, Publish to the device.
503
+ 6. Point them at `PLAYER_INSTALL.md` in the SDK for player install details.
404
504
 
405
505
  ---
406
506
 
407
507
  ## What not to ask / change
408
508
 
509
+ ### Forbidden questionnaire sources
510
+
511
+ - **`LLM_PROMPT.md`** — not used on Replit setup; its five questions are **replaced** by REPLIT_SETUP Questions 1–4
512
+ - Standalone “target platform” / “hosting target” / “use case” prompts outside Question 4
513
+
409
514
  Do **not** ask the user how to implement:
410
515
 
411
516
  - WebSocket framing
@@ -421,6 +526,8 @@ Do **not**:
421
526
  - Skip Cloudinary recommendation without stating the persistence tradeoff
422
527
  - Claim uploads are “permanent” on Replit local disk without Object Storage or Cloudinary
423
528
  - Leave `tsx` only in `devDependencies` if the Deploy pipeline installs production deps only
529
+ - Use Canvas preview as the primary CMS verification surface
530
+ - Serve a different app or API-only response at `/` instead of the Control Panel
424
531
 
425
532
  ---
426
533
 
@@ -446,9 +553,11 @@ TOMORROWOS_STORE=sqlite
446
553
 
447
554
  | Symptom | Likely cause | Fix |
448
555
  |---------|--------------|-----|
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 |
449
557
  | TV / browser: WebSocket handshake timeout | Node CMS not running or crash-loop | Fix Run → `npm run start`; check logs for `listening` |
450
558
  | Deploy/Publish fails / `tsx: not found` | `tsx` only in devDependencies | Move `tsx` to `dependencies`, reinstall, keep `start`: `tsx server.ts` |
451
559
  | Deploy runs wrong process | `.replit` / Deployment not `npm run start` | Set `run = "npm run start"` and `[deployment] run = ["sh", "-c", "npm run start"]` |
560
+ | `EADDRINUSE` on start | Old process holding port | Stop stale processes, clear background tasks, restart Repl |
452
561
  | Upload: `storage.objects.create` denied | Replit Object Storage IAM | Fix Object Storage permissions **or** switch to Cloudinary |
453
562
  | Upload OK then thumbnails vanish later | Non-persistent `public/uploads` | Object Storage or Cloudinary |
454
563
  | Supabase connection errors | Wrong URL or using reserved `DATABASE_URL` | Use `SUPABASE_URL` + `TOMORROWOS_STORE=supabase` |
@@ -458,4 +567,6 @@ TOMORROWOS_STORE=sqlite
458
567
 
459
568
  ## Protocol version
460
569
 
461
- `replit-setup/1.0` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
570
+ `replit-setup/1.1` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
571
+
572
+ **Changelog 1.1:** strict questionnaire scope; Replit must not use `LLM_PROMPT.md` questions (e.g. standalone target-platform prompt).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "0.7.6",
3
+ "version": "0.7.8",
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,6 +1,6 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "0.7.6",
3
+ "version": "0.7.8",
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.6",
16
+ "@tomorrowos/sdk": "^0.7.8",
17
17
  "dotenv": "^17.2.3",
18
18
  "tsx": "^4.19.0"
19
19
  },