@tomorrowos/sdk 0.8.0 → 0.8.2
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 +64 -48
- package/package.json +1 -1
- package/templates/cms-starter/package.json +2 -2
package/REPLIT_SETUP.md
CHANGED
|
@@ -12,7 +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 all setup questions are answered (including Cloudinary Secrets if you chose Cloudinary), configure and start — minimal verification only (Web app type + Preview at /). No Supabase or WebSocket tests.
|
|
15
|
+
After all setup questions are answered (including Cloudinary Secrets if you chose Cloudinary), configure and start — minimal verification only (Web app type + Preview at /). **Never test Supabase connection** — save `SUPABASE_URL` and move on. No Supabase or WebSocket tests.
|
|
16
16
|
Do not skip steps.
|
|
17
17
|
```
|
|
18
18
|
|
|
@@ -35,16 +35,15 @@ Replit Agent must ask **only** the questions defined in **this file**, in **this
|
|
|
35
35
|
|------|---------|------|
|
|
36
36
|
| 1 | **Question 1** — How many screens / devices? | Always |
|
|
37
37
|
| 2 | **Question 2** — Supabase connection | Only if answer to Q1 is **> 5** |
|
|
38
|
-
| 3 | **Question 3** — Media storage (Cloudinary
|
|
39
|
-
| 3b | **Question 3b** — Cloudinary credentials (Secrets) | **Mandatory** if Q3 answer is Cloudinary / yes — **before Q4** |
|
|
38
|
+
| 3 | **Question 3** — Media storage (+ Cloudinary Secrets if chosen) | Always (after Q1 or Q2) |
|
|
40
39
|
| 4 | **Question 4** — Brand / TomorrowOS app look | Always last, before execution |
|
|
41
40
|
|
|
42
|
-
**That is the complete list.** There are no other setup questions.
|
|
41
|
+
**That is the complete list.** There are no other setup questions. There is **no** “Question 3b” — Cloudinary credentials are collected **inside Question 3**, immediately after the user chooses Cloudinary.
|
|
43
42
|
|
|
44
|
-
**Critical:** Question 3 is **not complete** when the user says “Cloudinary” or “yes”. You **must**
|
|
43
|
+
**Critical:** Question 3 is **not complete** when the user says “Cloudinary” or “yes”. You **must** immediately show the Cloudinary Secrets input (same step — do **not** label a new question) and collect `CLOUDINARY_CLOUD_NAME`, `CLOUDINARY_API_KEY`, and `CLOUDINARY_API_SECRET` **before** Question 4. Do **not** skip to branding with placeholder or invented credentials.
|
|
45
44
|
|
|
46
45
|
|
|
47
|
-
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
|
|
46
|
+
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 are complete (Question 3 includes Cloudinary Secrets when applicable).
|
|
48
47
|
|
|
49
48
|
If the user says “just set it up, don’t ask questions,” respond:
|
|
50
49
|
|
|
@@ -56,21 +55,22 @@ Then ask **Question 1** — do not switch to `LLM_PROMPT.md`.
|
|
|
56
55
|
|
|
57
56
|
## Hard rules
|
|
58
57
|
|
|
59
|
-
1. **Ask only REPLIT_SETUP.md questions 1–4
|
|
60
|
-
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). **Exception:** Question
|
|
58
|
+
1. **Ask only REPLIT_SETUP.md questions 1–4** (see **Questionnaire scope**). Never use `LLM_PROMPT.md` on Replit.
|
|
59
|
+
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). **Exception:** If the user chooses Cloudinary in Question 3, **stay on Question 3** and immediately show the Secrets form — do **not** open a separate “3b” step or announce a new question number.
|
|
61
60
|
3. **Do not invent** screen counts, Cloudinary credentials, Supabase URLs, or brand colours.
|
|
62
61
|
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.
|
|
63
62
|
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.
|
|
64
63
|
6. **Never commit secrets** into git. Put credentials only in Replit **Secrets** (and optionally mirror non-secret flags in `.env` that reference env vars).
|
|
65
64
|
7. After Q&A, **configure and start** — do **not** run a long test suite (see **Post-Q&A: minimal verification only**).
|
|
66
65
|
8. **Follow the Runtime & Replit publish rules below exactly.** A project that cannot Deploy / Publish on Replit is incomplete.
|
|
66
|
+
9. **Supabase: configure only — never test.** Save `SUPABASE_URL` + `TOMORROWOS_STORE=supabase` and proceed. **Do not** ping Postgres, run `psql`, start the server solely to verify DB connectivity, or treat log errors like `ENOTFOUND` / `database connection failure` in **Replit dev / Preview** as a failed setup. Supabase often works only after **Publish** (production networking), not in the dev shell.
|
|
67
67
|
|
|
68
68
|
**Question order after Q1:**
|
|
69
69
|
|
|
70
|
-
- If **≤ 5 screens:** Q1 → Q3 →
|
|
71
|
-
- If **> 5 screens:** Q1 → Q2 → Q3 →
|
|
70
|
+
- If **≤ 5 screens:** Q1 → Q3 → Q4 → execution checklist
|
|
71
|
+
- If **> 5 screens:** Q1 → Q2 → Q3 → Q4 → execution checklist
|
|
72
72
|
|
|
73
|
-
Never insert extra questions between these steps.
|
|
73
|
+
Never insert extra questions between these steps. When the user chooses Cloudinary, **Question 3 continues** with the Secrets form immediately — then proceed to Q4 only after secrets are saved.
|
|
74
74
|
|
|
75
75
|
---
|
|
76
76
|
|
|
@@ -201,7 +201,7 @@ Allowed extras (optional): `"build-player": "tomorrowos build --platform tizen"`
|
|
|
201
201
|
"node": ">=20"
|
|
202
202
|
},
|
|
203
203
|
"dependencies": {
|
|
204
|
-
"@tomorrowos/sdk": "^0.8.
|
|
204
|
+
"@tomorrowos/sdk": "^0.8.2",
|
|
205
205
|
"dotenv": "^17.2.3",
|
|
206
206
|
"tsx": "^4.19.0"
|
|
207
207
|
},
|
|
@@ -301,6 +301,22 @@ Replace `YOUR-REPLIT-DOMAIN` with the actual published hostname (e.g. `my-cms.re
|
|
|
301
301
|
|
|
302
302
|
After Questions 1–4, **configure → `npm install` → `npm run start` → done.**
|
|
303
303
|
|
|
304
|
+
### Supabase: never test in Replit dev (mandatory)
|
|
305
|
+
|
|
306
|
+
When the user chose Supabase (>5 screens), setup is **save credentials + wire `server.ts` + start** — **nothing else**.
|
|
307
|
+
|
|
308
|
+
**Forbidden after Q&A (and after Question 2):**
|
|
309
|
+
|
|
310
|
+
- ❌ “Testing Supabase connection…”
|
|
311
|
+
- ❌ `psql`, `pg`, Prisma `db pull`, or any one-off DB probe script
|
|
312
|
+
- ❌ Restarting / debugging the server **because** logs show `database connection failure`, `getaddrinfo ENOTFOUND`, or `db.*.supabase.co can't be resolved`
|
|
313
|
+
- ❌ Telling the user their Supabase URL is wrong **only** because dev Preview cannot resolve the host
|
|
314
|
+
- ❌ Blocking setup completion on Supabase connectivity
|
|
315
|
+
|
|
316
|
+
**Expected in Replit dev:** Supabase host may **not resolve** in the dev environment. That is **normal**. The Control Panel at `/` can still load. Mark setup **complete** when Web app type is correct and Preview shows the Control Panel — **even if** Supabase errors appear in logs.
|
|
317
|
+
|
|
318
|
+
**When Supabase actually gets validated:** after the user **Publishes** the Repl and uses the live URL — not during the setup wizard.
|
|
319
|
+
|
|
304
320
|
### Do (maximum)
|
|
305
321
|
|
|
306
322
|
1. Confirm **Web app** artifact (not API) — **most important**.
|
|
@@ -311,7 +327,7 @@ After Questions 1–4, **configure → `npm install` → `npm run start` → don
|
|
|
311
327
|
|
|
312
328
|
### Do NOT run after setup (unless user asks or Publish fails)
|
|
313
329
|
|
|
314
|
-
- ❌ **Supabase connection test** (no `psql`, no DB ping, no “
|
|
330
|
+
- ❌ **Supabase connection test** — **never**, including after `npm run start` (no `psql`, no DB ping, no “verifying database…”, no retry loops for `ENOTFOUND`)
|
|
315
331
|
- ❌ **Cloudinary upload test**
|
|
316
332
|
- ❌ **`curl` / `fetch` on `/brand.json`** as a formal gate
|
|
317
333
|
- ❌ **Browser WebSocket console snippet** as a formal gate
|
|
@@ -319,7 +335,7 @@ After Questions 1–4, **configure → `npm install` → `npm run start` → don
|
|
|
319
335
|
- ❌ **Long troubleshooting loops** when Preview already shows the Control Panel
|
|
320
336
|
- ❌ Re-running the full **Publish readiness checklist** item-by-item in chat
|
|
321
337
|
|
|
322
|
-
If Preview shows the Control Panel and the project is **Web app** type, **stop testing** and give the user their URL and next steps
|
|
338
|
+
If Preview shows the Control Panel and the project is **Web app** type, **stop testing** and give the user their URL and next steps — **even when using Supabase and dev logs show DB connection errors**.
|
|
323
339
|
|
|
324
340
|
### Only if Preview is empty or Publish fails
|
|
325
341
|
|
|
@@ -402,7 +418,7 @@ DATABASE_SSL=true
|
|
|
402
418
|
```
|
|
403
419
|
|
|
404
420
|
5. **Do not** write the real password into committed files.
|
|
405
|
-
6. **Do not** test the Supabase connection after saving the Secret — configuration only.
|
|
421
|
+
6. **Do not** test the Supabase connection after saving the Secret — **configuration only**. No probe, no `npm run start` just to verify DB, no fixing “connection failure” in dev. Saving `SUPABASE_URL` completes Question 2.
|
|
406
422
|
|
|
407
423
|
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.
|
|
408
424
|
|
|
@@ -410,6 +426,8 @@ If the user refuses Supabase but chose > 5 screens, warn them SQLite on Replit i
|
|
|
410
426
|
|
|
411
427
|
## Question 3 — Media storage (uploads / thumbnails)
|
|
412
428
|
|
|
429
|
+
### Step A — Ask storage choice
|
|
430
|
+
|
|
413
431
|
**Ask exactly:**
|
|
414
432
|
|
|
415
433
|
> How should playlist media (images/videos) be stored?
|
|
@@ -422,47 +440,38 @@ If the user refuses Supabase but chose > 5 screens, warn them SQLite on Replit i
|
|
|
422
440
|
>
|
|
423
441
|
> Do you want me to set up **Cloudinary**? (yes / no)
|
|
424
442
|
|
|
425
|
-
### If YES
|
|
443
|
+
### Step B — If YES / Cloudinary (same Question 3 — no “3b”, no extra question)
|
|
426
444
|
|
|
427
|
-
|
|
445
|
+
**Do this immediately** when the user chooses Cloudinary. **Do not** say “Question 3b”, “next step”, or “Great — I’ll use Cloudinary” as a separate message before the form. **Go straight to the Secrets input.**
|
|
428
446
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
## Question 3b — Cloudinary credentials (mandatory if Q3 = Cloudinary)
|
|
447
|
+
**Preferred on Replit:** open the **Replit Secrets** UI with fields for:
|
|
432
448
|
|
|
433
|
-
|
|
449
|
+
- `CLOUDINARY_CLOUD_NAME`
|
|
450
|
+
- `CLOUDINARY_API_KEY`
|
|
451
|
+
- `CLOUDINARY_API_SECRET`
|
|
452
|
+
- Optional: `CLOUDINARY_FOLDER` (e.g. `tomorrowos`)
|
|
434
453
|
|
|
435
|
-
**
|
|
454
|
+
**If Secrets UI is unavailable, ask exactly (one message with all fields):**
|
|
436
455
|
|
|
437
|
-
>
|
|
438
|
-
>
|
|
439
|
-
> Please paste your Cloudinary credentials (from [cloudinary.com/console](https://cloudinary.com/console) → Dashboard → **API Keys**). I will store them as Replit **Secrets** — never in committed files:
|
|
440
|
-
>
|
|
441
|
-
> 1. **`CLOUDINARY_CLOUD_NAME`** — your cloud name (e.g. `dxyz123abc`)
|
|
442
|
-
> 2. **`CLOUDINARY_API_KEY`** — API Key
|
|
443
|
-
> 3. **`CLOUDINARY_API_SECRET`** — API Secret
|
|
456
|
+
> Paste your Cloudinary credentials (from [cloudinary.com/console](https://cloudinary.com/console) → Dashboard → **API Keys**). I will store them as Replit **Secrets**:
|
|
444
457
|
>
|
|
445
|
-
>
|
|
458
|
+
> 1. **`CLOUDINARY_CLOUD_NAME`**
|
|
459
|
+
> 2. **`CLOUDINARY_API_KEY`**
|
|
460
|
+
> 3. **`CLOUDINARY_API_SECRET`**
|
|
446
461
|
>
|
|
447
|
-
>
|
|
462
|
+
> Optional: **`CLOUDINARY_FOLDER`**
|
|
448
463
|
|
|
449
464
|
**You must then:**
|
|
450
465
|
|
|
451
|
-
1.
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
- `CLOUDINARY_API_SECRET=<user value>`
|
|
455
|
-
- Optional: `CLOUDINARY_FOLDER=<user value>`
|
|
456
|
-
2. **Do not** write real secrets into `.env` files that are committed to git. Replit Secrets only (or `.env` that is gitignored and references env vars).
|
|
457
|
-
3. **Do not** invent or placeholder Cloudinary credentials.
|
|
466
|
+
1. Save Replit Secrets: `CLOUDINARY_CLOUD_NAME`, `CLOUDINARY_API_KEY`, `CLOUDINARY_API_SECRET` (and optional `CLOUDINARY_FOLDER`).
|
|
467
|
+
2. **Do not** write real secrets into committed files.
|
|
468
|
+
3. **Do not** invent or placeholder credentials.
|
|
458
469
|
4. **Do not** proceed to Question 4 until all three required Secrets exist.
|
|
459
470
|
5. **Do not** run a Cloudinary upload test — configuration only.
|
|
460
471
|
|
|
461
|
-
|
|
472
|
+
**If the user does not have a Cloudinary account yet:** tell them to sign up at cloudinary.com and return with API keys. **Wait** on Question 3 — do not skip to Question 4.
|
|
462
473
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
**If the user does not have a Cloudinary account yet:** tell them to sign up at cloudinary.com, create API keys, then return with the three values. **Wait** — do not skip to Question 4.
|
|
474
|
+
The SDK auto-detects these env vars and uploads media to Cloudinary. New uploads will return `https://res.cloudinary.com/...` URLs.
|
|
466
475
|
|
|
467
476
|
### If NO — Replit Object Storage (or local)
|
|
468
477
|
|
|
@@ -600,13 +609,13 @@ npm run start
|
|
|
600
609
|
|
|
601
610
|
(Use `npm run dev` only for local edit/watch. **Publish / Deploy / Replit Run must use `npm run start`.**)
|
|
602
611
|
|
|
603
|
-
**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.
|
|
612
|
+
**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. **Ignore** Supabase `ENOTFOUND` / `database connection failure` in dev logs; do not debug DB for that reason alone.
|
|
604
613
|
|
|
605
614
|
### F. Done — skip extended verification
|
|
606
615
|
|
|
607
616
|
If the **three-item Publish readiness checklist** passes (especially **Web app, not API**), mark setup complete.
|
|
608
617
|
|
|
609
|
-
**Do not** run WebSocket console tests, Supabase connection tests, or `brand.json` curl checks here.
|
|
618
|
+
**Do not** run WebSocket console tests, Supabase connection tests, or `brand.json` curl checks here. **Supabase `ENOTFOUND` in dev is not a setup failure** — tell the user DB will connect after Publish if needed.
|
|
610
619
|
|
|
611
620
|
Only investigate further if Preview is empty, server crashed, or user reports Publish failure.
|
|
612
621
|
|
|
@@ -641,7 +650,8 @@ Do **not**:
|
|
|
641
650
|
- Change the production start command away from `tsx server.ts` / `npm run start`
|
|
642
651
|
- Point Supabase at Replit’s reserved `DATABASE_URL` when `SUPABASE_URL` should be used
|
|
643
652
|
- Skip Cloudinary recommendation without stating the persistence tradeoff
|
|
644
|
-
- **Skip
|
|
653
|
+
- **Skip Cloudinary Secrets** after the user chooses Cloudinary — always collect `CLOUDINARY_*` inside Question 3 before Question 4
|
|
654
|
+
- **Announce “Question 3b”** or a separate follow-up question — show the Secrets form immediately instead
|
|
645
655
|
- Claim uploads are “permanent” on Replit local disk without Object Storage or Cloudinary
|
|
646
656
|
- Leave `tsx` only in `devDependencies` if the Deploy pipeline installs production deps only
|
|
647
657
|
- Use Canvas preview as the primary CMS verification surface
|
|
@@ -649,6 +659,7 @@ Do **not**:
|
|
|
649
659
|
- Create the Repl as **API-only** or publish with **Static Deployment** only
|
|
650
660
|
- Omit `[[ports]]` / `deploymentTarget` from `.replit` when setting up for Publish
|
|
651
661
|
- Run **Supabase connection tests**, **WebSocket console tests**, or other post-setup smoke tests unless Preview fails or the user asks
|
|
662
|
+
- **Debug or “fix” Supabase** because dev logs show `getaddrinfo ENOTFOUND` or `database connection failure` — save config and finish setup instead
|
|
652
663
|
|
|
653
664
|
---
|
|
654
665
|
|
|
@@ -682,15 +693,20 @@ TOMORROWOS_STORE=sqlite
|
|
|
682
693
|
| `EADDRINUSE` on start | Old process holding port | Stop stale processes, clear background tasks, restart Repl |
|
|
683
694
|
| Upload: `storage.objects.create` denied | Replit Object Storage IAM | Fix Object Storage permissions **or** switch to Cloudinary |
|
|
684
695
|
| Upload OK then thumbnails vanish later | Non-persistent `public/uploads` | Object Storage or Cloudinary |
|
|
685
|
-
| Supabase
|
|
696
|
+
| Supabase `ENOTFOUND` / `can't be resolved` in **dev** logs after setup | Replit dev network cannot reach Supabase host | **Not a setup failure.** Finish wizard; user validates DB after **Publish** |
|
|
697
|
+
| Supabase connection errors on **published** URL | Wrong URL or using reserved `DATABASE_URL` | Use `SUPABASE_URL` + `TOMORROWOS_STORE=supabase`; pooler URL `*.pooler.supabase.com:6543` |
|
|
686
698
|
| Pairing works on one Repl but not another | That Repl’s WS/backend only | Compare Run command and logs with a known-good Repl |
|
|
687
699
|
|
|
688
700
|
---
|
|
689
701
|
|
|
690
702
|
## Protocol version
|
|
691
703
|
|
|
692
|
-
`replit-setup/1.
|
|
704
|
+
`replit-setup/1.6` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
|
|
705
|
+
|
|
706
|
+
**Changelog 1.6:** **Never test Supabase** in Replit dev — `ENOTFOUND` / connection errors in Preview logs are expected; setup completes when Control Panel loads.
|
|
707
|
+
|
|
708
|
+
**Changelog 1.5:** Cloudinary Secrets collected **inside Question 3** — no separate “3b” step; show Secrets form immediately when user picks Cloudinary.
|
|
693
709
|
|
|
694
|
-
**Changelog 1.4:**
|
|
710
|
+
**Changelog 1.4:** mandatory Cloudinary credential collection before Question 4 (superseded by 1.5 flow).
|
|
695
711
|
|
|
696
712
|
**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.8.
|
|
3
|
+
"version": "0.8.2",
|
|
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.8.
|
|
3
|
+
"version": "0.8.2",
|
|
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.8.
|
|
16
|
+
"@tomorrowos/sdk": "^0.8.2",
|
|
17
17
|
"dotenv": "^17.2.3",
|
|
18
18
|
"tsx": "^4.19.0"
|
|
19
19
|
},
|