@tomorrowos/sdk 0.7.5 → 0.7.7

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
@@ -30,6 +30,139 @@ Alternate triggers that also activate this protocol:
30
30
  - HTTP Control Panel loads
31
31
  - `GET /brand.json` returns 200
32
32
  - 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.
34
+
35
+ ---
36
+
37
+ ## Runtime & Replit publish rules (mandatory)
38
+
39
+ These rules exist so the CMS can be **Run** and **Published/Deployed** on Replit without custom build steps.
40
+
41
+ ### Runtime
42
+
43
+ - The server **must** run directly from source using `tsx server.ts`.
44
+ - **Do not** compile to `dist/` as the production entrypoint.
45
+ - **Do not** replace `@tomorrowos/sdk` with a hand-rolled server, Express wrapper that drops WebSocket upgrades, or a different package name.
46
+ - Always depend on **`@tomorrowos/sdk`**.
47
+ - **`tsx` must be available at runtime.** Prefer putting `tsx` in **`dependencies`** (not only `devDependencies`) so Replit Deploy / production installs still include it.
48
+ - Use **Node.js 20 or newer** (set in `.replit` / Nix / package engines if the workspace asks).
49
+
50
+ ### Expected `package.json` scripts
51
+
52
+ ```json
53
+ {
54
+ "scripts": {
55
+ "dev": "tsx watch server.ts",
56
+ "start": "tsx server.ts"
57
+ }
58
+ }
59
+ ```
60
+
61
+ Allowed extras (optional): `"build-player": "tomorrowos build --platform tizen"`.
62
+ **Forbidden as the Deploy entrypoint:** `node dist/server.js`, `next start`, static-only hosts, or any command that does not start `TomorrowOS.listen(...)`.
63
+
64
+ ### Minimal dependency expectations
65
+
66
+ ```json
67
+ {
68
+ "type": "module",
69
+ "engines": {
70
+ "node": ">=20"
71
+ },
72
+ "dependencies": {
73
+ "@tomorrowos/sdk": "^0.7.7",
74
+ "dotenv": "^17.2.3",
75
+ "tsx": "^4.19.0"
76
+ },
77
+ "devDependencies": {
78
+ "@types/node": "^20.0.0",
79
+ "typescript": "^5.5.0"
80
+ },
81
+ "scripts": {
82
+ "dev": "tsx watch server.ts",
83
+ "start": "tsx server.ts"
84
+ }
85
+ }
86
+ ```
87
+
88
+ Bump `@tomorrowos/sdk` to the latest published version when scaffolding.
89
+
90
+ ### Replit Run command
91
+
92
+ ```text
93
+ npm run start
94
+ ```
95
+
96
+ ### Replit deployment / publish command
97
+
98
+ ```text
99
+ npm run start
100
+ ```
101
+
102
+ ### `.replit` (create or edit)
103
+
104
+ ```toml
105
+ run = "npm run start"
106
+
107
+ [deployment]
108
+ run = ["sh", "-c", "npm run start"]
109
+ ```
110
+
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`.
112
+
113
+ ### Publish readiness checklist (before telling the user “done”)
114
+
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.)
126
+
127
+ If any item fails, fix it before finishing.
128
+
129
+ ### Preview requirements (Replit workspace)
130
+
131
+ The Replit **Preview** must show the **TomorrowOS Control Panel** at `/` (root URL).
132
+
133
+ - `GET /` must serve the CMS Control Panel (`public/index.html` via `staticRoot: public`).
134
+ - **Do not** serve another app, API-only landing page, or placeholder at `/`.
135
+ - **Do not** use or rely on the **Canvas** preview for this CMS — use the normal **Web** preview in the browser.
136
+ - If the preview is **empty** or shows the wrong thing:
137
+ 1. Confirm the Replit project type is **Web**, not **API**.
138
+ 2. Confirm `npm run start` is running and logs show `[TomorrowOS] listening on http://0.0.0.0:...`
139
+ 3. Confirm `server.ts` calls `tomorrowos.listen({ staticRoot: join(__dirname, "public"), ... })`
140
+ 4. Open the preview URL directly (not Canvas) and hard-refresh.
141
+
142
+ ### Before publishing / deploying
143
+
144
+ Do this **before** clicking Publish / Deploy:
145
+
146
+ 1. **Stop** stale running processes (old `tsx` / `node` servers from prior attempts).
147
+ 2. **Clear** old background tasks from previous failed projects (Replit Shell / Processes panel).
148
+ 3. **Ensure no old process is holding the port** (`EADDRINUSE` in logs = something still bound to `PORT`).
149
+ 4. **Restart the Replit workspace** if the port is stuck or preview still shows a ghost app.
150
+ 5. Run `npm run start` once cleanly and confirm Control Panel loads at `/` in preview.
151
+
152
+ ### After publishing / deploying
153
+
154
+ Tell the user their live CMS URLs:
155
+
156
+ - **Control Panel (browser):** `https://YOUR-REPLIT-DOMAIN`
157
+ - **TV / player CMS endpoint:** same HTTPS origin, e.g. `https://YOUR-REPLIT-DOMAIN/` (player converts `https://` → `wss://` for WebSocket)
158
+
159
+ Replace `YOUR-REPLIT-DOMAIN` with the actual published hostname (e.g. `my-cms.replit.app`).
160
+
161
+ Verify after publish:
162
+
163
+ 1. `https://YOUR-REPLIT-DOMAIN/` shows the Control Panel (not empty, not API docs).
164
+ 2. `https://YOUR-REPLIT-DOMAIN/brand.json` returns 200.
165
+ 3. WebSocket to `wss://YOUR-REPLIT-DOMAIN/` succeeds.
33
166
 
34
167
  ---
35
168
 
@@ -251,24 +384,51 @@ CLOUDINARY_API_SECRET=...
251
384
  - Supabase path: pass `databaseUrl: process.env.SUPABASE_URL || process.env.DATABASE_URL` into `createTomorrowOSStore`
252
385
  - Keep TomorrowOS event handlers from the starter (paired / online policy push)
253
386
 
254
- ### D. Install and run
387
+ ### D. Runtime files for Replit publish
388
+
389
+ 1. Ensure `package.json` scripts are exactly:
390
+
391
+ ```json
392
+ "dev": "tsx watch server.ts",
393
+ "start": "tsx server.ts"
394
+ ```
395
+
396
+ 2. Move / keep `tsx` in **`dependencies`** so Deploy works.
397
+ 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
+ ```
406
+
407
+ ### E. Install and run
408
+
409
+ **Before starting:** stop stale processes, clear old background tasks, free the port if needed, restart workspace if stuck.
255
410
 
256
411
  ```bash
257
412
  npm install
258
- npm run dev
413
+ npm run start
259
414
  ```
260
415
 
416
+ (Use `npm run dev` only for local edit/watch. **Publish / Deploy / Replit Run must use `npm run start`.**)
417
+
261
418
  Confirm logs contain something like:
262
419
 
263
420
  ```text
264
421
  [TomorrowOS] listening on http://0.0.0.0:<PORT>
265
422
  ```
266
423
 
267
- ### E. Verify before telling the user “done”
424
+ Confirm the **Web preview** (not Canvas) shows the Control Panel at `/`.
268
425
 
269
- 1. Open the Control Panel URL.
270
- 2. `GET /brand.json` → 200 and correct `name` / colours.
271
- 3. In browser console on the Control Panel origin:
426
+ ### F. Verify before telling the user “done”
427
+
428
+ 1. Replit project type is **Web**; preview at `/` shows Control Panel (not empty, not Canvas-only).
429
+ 2. Open the Control Panel URL.
430
+ 3. `GET /brand.json` → 200 and correct `name` / colours.
431
+ 4. In browser console on the Control Panel origin:
272
432
 
273
433
  ```javascript
274
434
  const ws = new WebSocket(location.origin.replace(/^http/, "ws") + "/");
@@ -276,15 +436,18 @@ ws.onopen = () => console.log("WS OK");
276
436
  ws.onerror = (e) => console.log("WS ERR", e);
277
437
  ```
278
438
 
439
+ 5. Confirm the **Publish readiness checklist** in **Runtime & Replit publish rules**.
440
+
279
441
  If WebSocket fails, fix Run command / process crash / sleep **before** asking the user to pair a TV.
280
442
 
281
- ### F. Tell the user next steps (no code)
443
+ ### G. Tell the user next steps (no code)
282
444
 
283
445
  1. Keep this Repl **running** (Always On if available).
284
- 2. On the TomorrowOS player, enter the CMS URL: `https://<your-repl>.replit.app/`
285
- 3. Enter the 6-character pairing code from the screen into the Control Panel.
286
- 4. Create a playlist, upload media, Publish to the device.
287
- 5. Point them at `PLAYER_INSTALL.md` in the SDK for player install details.
446
+ 2. **Published Control Panel URL:** `https://YOUR-REPLIT-DOMAIN`
447
+ 3. On the TomorrowOS player, enter the CMS URL: `https://YOUR-REPLIT-DOMAIN/`
448
+ 4. Enter the 6-character pairing code from the screen into the Control Panel.
449
+ 5. Create a playlist, upload media, Publish to the device.
450
+ 6. Point them at `PLAYER_INSTALL.md` in the SDK for player install details.
288
451
 
289
452
  ---
290
453
 
@@ -300,9 +463,13 @@ Do **not** ask the user how to implement:
300
463
  Do **not**:
301
464
 
302
465
  - Replace `@tomorrowos/sdk` with a hand-rolled server
466
+ - Change the production start command away from `tsx server.ts` / `npm run start`
303
467
  - Point Supabase at Replit’s reserved `DATABASE_URL` when `SUPABASE_URL` should be used
304
468
  - Skip Cloudinary recommendation without stating the persistence tradeoff
305
469
  - Claim uploads are “permanent” on Replit local disk without Object Storage or Cloudinary
470
+ - Leave `tsx` only in `devDependencies` if the Deploy pipeline installs production deps only
471
+ - Use Canvas preview as the primary CMS verification surface
472
+ - Serve a different app or API-only response at `/` instead of the Control Panel
306
473
 
307
474
  ---
308
475
 
@@ -328,7 +495,11 @@ TOMORROWOS_STORE=sqlite
328
495
 
329
496
  | Symptom | Likely cause | Fix |
330
497
  |---------|--------------|-----|
331
- | TV / browser: WebSocket handshake timeout | Node CMS not running or crash-loop | Fix Run `npm start` / `npm run dev`; check logs for `listening` |
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 |
499
+ | TV / browser: WebSocket handshake timeout | Node CMS not running or crash-loop | Fix Run → `npm run start`; check logs for `listening` |
500
+ | Deploy/Publish fails / `tsx: not found` | `tsx` only in devDependencies | Move `tsx` to `dependencies`, reinstall, keep `start`: `tsx server.ts` |
501
+ | Deploy runs wrong process | `.replit` / Deployment not `npm run start` | Set `run = "npm run start"` and `[deployment] run = ["sh", "-c", "npm run start"]` |
502
+ | `EADDRINUSE` on start | Old process holding port | Stop stale processes, clear background tasks, restart Repl |
332
503
  | Upload: `storage.objects.create` denied | Replit Object Storage IAM | Fix Object Storage permissions **or** switch to Cloudinary |
333
504
  | Upload OK then thumbnails vanish later | Non-persistent `public/uploads` | Object Storage or Cloudinary |
334
505
  | Supabase connection errors | Wrong URL or using reserved `DATABASE_URL` | Use `SUPABASE_URL` + `TOMORROWOS_STORE=supabase` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "0.7.5",
3
+ "version": "0.7.7",
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",
@@ -0,0 +1,4 @@
1
+ run = "npm run start"
2
+
3
+ [deployment]
4
+ run = ["sh", "-c", "npm run start"]
@@ -1,21 +1,24 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "0.7.5",
3
+ "version": "0.7.7",
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",
7
+ "engines": {
8
+ "node": ">=20"
9
+ },
7
10
  "scripts": {
8
11
  "dev": "tsx watch server.ts",
9
12
  "start": "tsx server.ts",
10
13
  "build-player": "tomorrowos build --platform tizen"
11
14
  },
12
15
  "dependencies": {
13
- "@tomorrowos/sdk": "^0.7.5",
14
- "dotenv": "^17.2.3"
16
+ "@tomorrowos/sdk": "^0.7.7",
17
+ "dotenv": "^17.2.3",
18
+ "tsx": "^4.19.0"
15
19
  },
16
20
  "devDependencies": {
17
21
  "@types/node": "^20.0.0",
18
- "tsx": "^4.19.0",
19
22
  "typescript": "^5.5.0"
20
23
  }
21
24
  }