@tomorrowos/sdk 0.9.40 → 0.9.42
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/LOVABLE_SETUP.md +67 -67
- package/README.md +4 -3
- package/REPLIT_SETUP.md +115 -44
- package/VERCEL_QUESTIONS.md +22 -22
- package/VERCEL_SETUP.md +200 -200
- package/package.json +1 -1
- package/templates/cms-starter/package.json +2 -2
- package/templates/cms-starter/public/methods.js +37 -0
- package/templates/cms-starter/public/panel.css +21 -12
- package/templates/cms-starter-v0/cms-panel/methods.js +37 -0
- package/templates/cms-starter-v0/cms-panel/panel.css +21 -12
- package/templates/cms-starter-v0/package.json +2 -2
package/REPLIT_SETUP.md
CHANGED
|
@@ -12,9 +12,11 @@ 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
|
-
Artifact kind must be **web** (never **api**).
|
|
15
|
+
Artifact kind must be **web** (never **api**).
|
|
16
|
+
Question 1 database options in this order: 1) Supabase (Recommended) 2) Built-in Replit PostgreSQL 3) SQLite.
|
|
17
|
+
If Supabase: collect SUPABASE_URL once only — never ask for the connection string twice.
|
|
16
18
|
Question 3 branding fields are all optional; missing values keep starter brand.json defaults.
|
|
17
|
-
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
|
|
19
|
+
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 database connection** in Preview — configure and move on. No DB or WebSocket tests.
|
|
18
20
|
Do not skip steps.
|
|
19
21
|
```
|
|
20
22
|
|
|
@@ -59,13 +61,18 @@ Replit Agent must ask **only** the questions defined in **this file**, in **this
|
|
|
59
61
|
|
|
60
62
|
| Step | Section | When |
|
|
61
63
|
|------|---------|------|
|
|
62
|
-
| 1 | **Question 1** — Supabase
|
|
64
|
+
| 1 | **Question 1** — Database choice (Supabase → Replit Postgres → SQLite) | Always |
|
|
63
65
|
| 2 | **Question 2** — Media storage (+ Cloudinary Secrets if chosen) | Always (after Q1) |
|
|
64
66
|
| 3 | **Question 3** — Brand / TomorrowOS app look (**all fields optional**) | Always last, before execution |
|
|
65
67
|
|
|
66
68
|
**That is the complete list.** There are no other setup questions. **Do not** ask how many screens / devices. There is **no** “Question 2b” — Cloudinary credentials are collected **inside Question 2**, immediately after the user chooses Cloudinary.
|
|
67
69
|
|
|
68
|
-
**Critical — Question 1 (
|
|
70
|
+
**Critical — Question 1 option order (exact):** Present database choices in **this order only**:
|
|
71
|
+
1. **Supabase Postgres (Recommended)**
|
|
72
|
+
2. **Built-in Replit PostgreSQL**
|
|
73
|
+
3. **SQLite (local file — fine for testing)**
|
|
74
|
+
|
|
75
|
+
**Critical — Supabase path collected once only:** If the user picks Supabase, collect `SUPABASE_URL` in **one** step (Secrets UI **or** chat paste — not both). After it is saved, **never** ask for the connection string / `SUPABASE_URL` again (not in Q2, Q3, execution, Publish, or “confirm Secrets”).
|
|
69
76
|
|
|
70
77
|
**Critical:** Question 2 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 3. Do **not** skip to branding with placeholder or invented credentials.
|
|
71
78
|
|
|
@@ -75,7 +82,7 @@ If the user volunteers extra info early (e.g. brand name before Q3), **record it
|
|
|
75
82
|
|
|
76
83
|
If the user says “just set it up, don’t ask questions,” respond:
|
|
77
84
|
|
|
78
|
-
> I need a few quick answers from REPLIT_SETUP.md (Supabase
|
|
85
|
+
> I need a few quick answers from REPLIT_SETUP.md (database choice — Supabase recommended, then Replit Postgres, then SQLite — media storage — plus Cloudinary credentials if you choose Cloudinary — and optional branding). It takes about a minute and ensures the CMS deploys correctly on Replit.
|
|
79
86
|
|
|
80
87
|
Then ask **Question 1** — do not switch to `LLM_PROMPT.md`.
|
|
81
88
|
|
|
@@ -86,14 +93,15 @@ Then ask **Question 1** — do not switch to `LLM_PROMPT.md`.
|
|
|
86
93
|
1. **Ask only REPLIT_SETUP.md questions 1–3** (see **Questionnaire scope**). Never use `LLM_PROMPT.md` on Replit.
|
|
87
94
|
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 2, **stay on Question 2** and immediately show the Secrets form — do **not** open a separate “2b” step or announce a new question number.
|
|
88
95
|
3. **Do not invent** Cloudinary credentials, Supabase URLs, or brand colours. **Do not ask** screen / device count.
|
|
89
|
-
4. **Do not use Replit’s reserved `DATABASE_URL` Secret for Supabase.** On Replit, `DATABASE_URL` is often
|
|
90
|
-
4a. **
|
|
96
|
+
4. **Do not use Replit’s reserved `DATABASE_URL` Secret for Supabase.** On Replit, `DATABASE_URL` is often the **built-in Replit PostgreSQL** URL. For Supabase always use **`SUPABASE_URL`**. For built-in Replit Postgres, use **`DATABASE_URL`** with `TOMORROWOS_STORE=postgres`.
|
|
97
|
+
4a. **If Supabase is chosen: never collect `SUPABASE_URL` twice.** One capture after the choice is enough for the whole wizard and execution checklist.
|
|
91
98
|
4b. **Question 3 fields are all optional.** Missing values → keep starter `brand.json` defaults; do not block or re-prompt.
|
|
99
|
+
4c. **`TOMORROWOS_STORE` + `DATABASE_SSL` are agent-owned.** After the Q1 choice (and URL if needed), set them yourself. Never ask the user to type those names/values.
|
|
92
100
|
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.
|
|
93
101
|
6. **Never commit secrets** into git. Put credentials only in Replit **Secrets** (and optionally mirror non-secret flags in `.env` that reference env vars).
|
|
94
102
|
7. After Q&A, **configure and start** — do **not** run a long test suite (see **Post-Q&A: minimal verification only**).
|
|
95
103
|
8. **Follow the Runtime & Replit publish rules below exactly.** A project that cannot Deploy / Publish on Replit is incomplete.
|
|
96
|
-
9. **
|
|
104
|
+
9. **Database: configure only — never test in Preview.** Save store Secrets / flags and proceed. **Do not** ping Postgres, run `psql`, or treat `ENOTFOUND` / `database connection failure` in **Replit dev / Preview** as a failed setup (especially Supabase).
|
|
97
105
|
10. **Artifact kind = `web` only.** **`kind = "api"` is forbidden** for the TomorrowOS CMS artifact. See **IRON RULE** above. Setup is incomplete if Publish would still see an `api` artifact.
|
|
98
106
|
|
|
99
107
|
**Question order (always):**
|
|
@@ -336,17 +344,17 @@ Replace `YOUR-REPLIT-DOMAIN` with the actual published hostname (e.g. `my-cms.re
|
|
|
336
344
|
|
|
337
345
|
After Questions 1–3, **configure → `npm install` → `npm run start` → done.**
|
|
338
346
|
|
|
339
|
-
###
|
|
347
|
+
### Database / Postgres: never test in Replit dev (mandatory)
|
|
340
348
|
|
|
341
|
-
|
|
349
|
+
After Q1, **save credentials / flags + wire `server.ts` + start** — **nothing else**.
|
|
342
350
|
|
|
343
351
|
**Forbidden after Q&A (and after Question 1):**
|
|
344
352
|
|
|
345
|
-
- ❌ “Testing Supabase connection…”
|
|
353
|
+
- ❌ “Testing Supabase / Postgres connection…”
|
|
346
354
|
- ❌ `psql`, `pg`, Prisma `db pull`, or any one-off DB probe script
|
|
347
355
|
- ❌ Restarting / debugging the server **because** logs show `database connection failure`, `getaddrinfo ENOTFOUND`, or `db.*.supabase.co can't be resolved`
|
|
348
356
|
- ❌ Telling the user their Supabase URL is wrong **only** because dev Preview cannot resolve the host
|
|
349
|
-
- ❌ Blocking setup completion on
|
|
357
|
+
- ❌ Blocking setup completion on database connectivity
|
|
350
358
|
|
|
351
359
|
**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.
|
|
352
360
|
|
|
@@ -362,7 +370,7 @@ Setup always uses Supabase: **save credentials + wire `server.ts` + start** —
|
|
|
362
370
|
|
|
363
371
|
### Do NOT run after setup (unless user asks or Publish fails)
|
|
364
372
|
|
|
365
|
-
- ❌ **
|
|
373
|
+
- ❌ **Database connection test** — **never**, including after `npm run start` (no `psql`, no DB ping, no “verifying database…”, no retry loops for `ENOTFOUND`)
|
|
366
374
|
- ❌ **Cloudinary upload test**
|
|
367
375
|
- ❌ **`curl` / `fetch` on `/brand.json`** as a formal gate
|
|
368
376
|
- ❌ **Browser WebSocket console snippet** as a formal gate
|
|
@@ -378,41 +386,94 @@ Then (and only then) check: API vs Web type → `.replit` ports/`deploymentTarge
|
|
|
378
386
|
|
|
379
387
|
---
|
|
380
388
|
|
|
381
|
-
## Question 1 —
|
|
389
|
+
## Question 1 — Database choice
|
|
390
|
+
|
|
391
|
+
> **This is the first setup question.** **Do not** ask how many screens / devices.
|
|
392
|
+
|
|
393
|
+
### Step A — Ask exactly (option order is mandatory)
|
|
394
|
+
|
|
395
|
+
Present **exactly these three options, in this order** (Supabase first / recommended):
|
|
396
|
+
|
|
397
|
+
> **Database choice**
|
|
398
|
+
>
|
|
399
|
+
> 1. **Supabase Postgres (Recommended)** — I have a connection string
|
|
400
|
+
> 2. **Built-in Replit PostgreSQL** — no external account needed
|
|
401
|
+
> 3. **SQLite** (local file — fine for testing)
|
|
402
|
+
>
|
|
403
|
+
> Which do you want?
|
|
382
404
|
|
|
383
|
-
|
|
405
|
+
**Forbidden option orders / labels:**
|
|
384
406
|
|
|
385
|
-
|
|
407
|
+
- ❌ Putting Built-in Replit PostgreSQL first or marking it “recommended”
|
|
408
|
+
- ❌ Omitting Supabase or SQLite
|
|
409
|
+
- ❌ Asking only for a connection string without showing this choice first (unless `SUPABASE_URL` is already saved and the user is continuing a prior Supabase setup)
|
|
386
410
|
|
|
387
|
-
|
|
411
|
+
**Agent auto-sets after the choice** (never ask the user to type these):
|
|
412
|
+
|
|
413
|
+
| Choice | Agent sets | User provides |
|
|
414
|
+
|--------|------------|---------------|
|
|
415
|
+
| 1 Supabase | `TOMORROWOS_STORE=supabase`, `DATABASE_SSL=true` | `SUPABASE_URL` (**once**) |
|
|
416
|
+
| 2 Replit PostgreSQL | `TOMORROWOS_STORE=postgres`, `DATABASE_SSL=true` | Use Replit’s built-in **`DATABASE_URL`** (do not ask them to invent a URI) |
|
|
417
|
+
| 3 SQLite | `TOMORROWOS_STORE=sqlite` | Confirmation only |
|
|
418
|
+
|
|
419
|
+
### Step B1 — If **1 Supabase (Recommended)**
|
|
420
|
+
|
|
421
|
+
Collect `SUPABASE_URL` **exactly once** (IRON RULE).
|
|
388
422
|
|
|
389
423
|
| Allowed (pick **one**) | Forbidden |
|
|
390
424
|
|------------------------|-----------|
|
|
391
|
-
| Open the Replit **Secrets** UI for `SUPABASE_URL` **or** ask the user to paste the string in chat | Asking
|
|
425
|
+
| Open the Replit **Secrets** UI for `SUPABASE_URL` **or** ask the user to paste the string in chat | Asking for the connection string again after Secrets was already filled |
|
|
392
426
|
| Save Secret once, then move on | Opening Secrets **and** also asking them to paste the same URI in chat |
|
|
393
427
|
| Reuse the saved Secret in execution | Asking again in Q2 / Q3 / “confirm your Supabase Secret” / Publish / checklist |
|
|
394
428
|
|
|
395
|
-
If `SUPABASE_URL` is **already** present in Replit Secrets when
|
|
429
|
+
If `SUPABASE_URL` is **already** present in Replit Secrets when this branch starts, **do not** ask for it again — confirm you will use the existing Secret and proceed to Question 2 (unless the user explicitly wants to replace it).
|
|
396
430
|
|
|
397
|
-
**Preferred on Replit:** open an **input / Secrets** UI
|
|
431
|
+
**Preferred on Replit:** open an **input / Secrets** UI for:
|
|
398
432
|
|
|
399
433
|
- `SUPABASE_URL`
|
|
400
434
|
|
|
401
|
-
**Only if** the Secrets UI is unavailable, ask exactly in chat
|
|
435
|
+
**Only if** the Secrets UI is unavailable, ask exactly in chat. **Do not** also open a second Secrets prompt for the same value:
|
|
402
436
|
|
|
403
|
-
> Paste your Supabase Postgres connection string below. I will store it as the Replit Secret **`SUPABASE_URL`** (not `DATABASE_URL` — that name is
|
|
437
|
+
> Paste your Supabase Postgres connection string below. I will store it as the Replit Secret **`SUPABASE_URL`** (not `DATABASE_URL` — that name is for built-in Replit PostgreSQL).
|
|
404
438
|
>
|
|
405
439
|
> Example shape: `postgresql://postgres.[PROJECT]:[PASSWORD]@aws-0-[REGION].pooler.supabase.com:6543/postgres`
|
|
406
440
|
>
|
|
407
|
-
> SSL is assumed **yes** for Supabase unless you say otherwise
|
|
441
|
+
> SSL is assumed **yes** for Supabase unless you say otherwise.
|
|
408
442
|
|
|
409
443
|
**You must then:**
|
|
410
444
|
|
|
411
445
|
1. Create / update Replit Secret: `SUPABASE_URL=<user value>` (**once**).
|
|
412
|
-
2.
|
|
446
|
+
2. Set flags yourself (not a second paste of the URI):
|
|
413
447
|
- `TOMORROWOS_STORE=supabase`
|
|
414
|
-
- `DATABASE_SSL=true`
|
|
415
|
-
3.
|
|
448
|
+
- `DATABASE_SSL=true`
|
|
449
|
+
3. Wire `server.ts` with `createTomorrowOSStore({ databaseUrl: process.env.SUPABASE_URL || process.env.DATABASE_URL, sqlitePath: ... })`.
|
|
450
|
+
4. **Do not** write the password into committed files.
|
|
451
|
+
5. **Do not** test the connection — configuration only.
|
|
452
|
+
6. **Do not** proceed to Question 2 until `SUPABASE_URL` is saved (or was already present and reused).
|
|
453
|
+
7. **After this branch completes, never re-request `SUPABASE_URL`.**
|
|
454
|
+
|
|
455
|
+
### Step B2 — If **2 Built-in Replit PostgreSQL**
|
|
456
|
+
|
|
457
|
+
1. Ensure Replit’s built-in Postgres is enabled for the Repl (create/attach if the platform UI requires it).
|
|
458
|
+
2. Use the platform-provided **`DATABASE_URL`** Secret — **do not** ask the user to paste a Supabase-style URI.
|
|
459
|
+
3. Set yourself:
|
|
460
|
+
- `TOMORROWOS_STORE=postgres`
|
|
461
|
+
- `DATABASE_SSL=true` (unless Replit docs for this DB say otherwise)
|
|
462
|
+
4. Wire `server.ts` with `databaseUrl: process.env.DATABASE_URL || process.env.SUPABASE_URL`.
|
|
463
|
+
5. **Do not** set `TOMORROWOS_STORE=supabase` for this path.
|
|
464
|
+
6. **Do not** ask for `SUPABASE_URL`.
|
|
465
|
+
7. **Do not** test the DB connection in Preview — configuration only.
|
|
466
|
+
8. Proceed to Question 2.
|
|
467
|
+
|
|
468
|
+
### Step B3 — If **3 SQLite**
|
|
469
|
+
|
|
470
|
+
1. Set `TOMORROWOS_STORE=sqlite` yourself.
|
|
471
|
+
2. Ensure `data/tomorrowos.db` path via starter / `createTomorrowOSStore({ sqlitePath: join(__dirname, "data", "tomorrowos.db") })`.
|
|
472
|
+
3. Warn briefly: SQLite is fine for testing; pairings may not survive some rebuilds as well as Postgres.
|
|
473
|
+
4. **Do not** ask for any connection string.
|
|
474
|
+
5. Proceed to Question 2.
|
|
475
|
+
|
|
476
|
+
### Shared `server.ts` shape (all Q1 paths)
|
|
416
477
|
|
|
417
478
|
```ts
|
|
418
479
|
import "dotenv/config";
|
|
@@ -425,7 +486,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
425
486
|
const brand = JSON.parse(readFileSync(join(__dirname, "brand.json"), "utf8"));
|
|
426
487
|
|
|
427
488
|
const store = createTomorrowOSStore({
|
|
428
|
-
//
|
|
489
|
+
// Supabase: SUPABASE_URL. Replit Postgres: DATABASE_URL. SQLite: ignores URL.
|
|
429
490
|
databaseUrl: process.env.SUPABASE_URL || process.env.DATABASE_URL,
|
|
430
491
|
sqlitePath: join(__dirname, "data", "tomorrowos.db")
|
|
431
492
|
});
|
|
@@ -439,15 +500,6 @@ tomorrowos.listen({
|
|
|
439
500
|
});
|
|
440
501
|
```
|
|
441
502
|
|
|
442
|
-
4. Ensure `.env` / Secrets include `TOMORROWOS_STORE=supabase` and `DATABASE_SSL=true`. The connection string itself lives **only** in the Secret already saved in step 1 — **do not** ask the user to paste it into `.env` or chat again.
|
|
443
|
-
|
|
444
|
-
5. **Do not** write the real password into committed files.
|
|
445
|
-
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 1.
|
|
446
|
-
7. **Do not** proceed to Question 2 until `SUPABASE_URL` is saved (or was already present and reused).
|
|
447
|
-
8. **After Question 1 completes, never re-request `SUPABASE_URL`.** Execution checklist step B must **reuse** the existing Secret — wire env / `server.ts` silently.
|
|
448
|
-
|
|
449
|
-
If the user refuses Supabase, warn that Replit fleets need a durable Postgres store, then offer SQLite only after they explicitly confirm.
|
|
450
|
-
|
|
451
503
|
**Store in `brand.json` later (Question 3):** `cms.hostingTarget`: `"here"`. Do **not** ask for `expectedScreens`; leave a default (e.g. `5`) when writing `brand.json`.
|
|
452
504
|
|
|
453
505
|
---
|
|
@@ -598,16 +650,31 @@ If `init` is inappropriate (existing customised project), merge carefully:
|
|
|
598
650
|
|
|
599
651
|
### B. Apply store + media Secrets
|
|
600
652
|
|
|
601
|
-
**
|
|
653
|
+
Apply **only** the path chosen in Question 1 — do not re-ask.
|
|
602
654
|
|
|
603
|
-
|
|
655
|
+
**If Q1 = Supabase (reuse; do not ask again):**
|
|
604
656
|
|
|
605
657
|
```env
|
|
606
658
|
TOMORROWOS_STORE=supabase
|
|
607
659
|
DATABASE_SSL=true
|
|
608
660
|
```
|
|
609
661
|
|
|
610
|
-
|
|
662
|
+
Use the **`SUPABASE_URL` already saved**. **Do not** prompt to paste it again.
|
|
663
|
+
|
|
664
|
+
**If Q1 = Built-in Replit PostgreSQL:**
|
|
665
|
+
|
|
666
|
+
```env
|
|
667
|
+
TOMORROWOS_STORE=postgres
|
|
668
|
+
DATABASE_SSL=true
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
Use Replit’s **`DATABASE_URL`**. **Do not** ask for `SUPABASE_URL`.
|
|
672
|
+
|
|
673
|
+
**If Q1 = SQLite:**
|
|
674
|
+
|
|
675
|
+
```env
|
|
676
|
+
TOMORROWOS_STORE=sqlite
|
|
677
|
+
```
|
|
611
678
|
|
|
612
679
|
**Cloudinary (if chosen):**
|
|
613
680
|
|
|
@@ -620,7 +687,7 @@ CLOUDINARY_API_SECRET=...
|
|
|
620
687
|
### C. Wire `server.ts`
|
|
621
688
|
|
|
622
689
|
- Always: `host: "0.0.0.0"`, `port: Number(process.env.PORT) || 3000`, `staticRoot: public`
|
|
623
|
-
-
|
|
690
|
+
- Store: `createTomorrowOSStore({ databaseUrl: process.env.SUPABASE_URL || process.env.DATABASE_URL, sqlitePath: ... })` — driver comes from `TOMORROWOS_STORE`
|
|
624
691
|
- Keep TomorrowOS event handlers from the starter (paired / online policy push)
|
|
625
692
|
|
|
626
693
|
### D. Runtime files for Replit publish
|
|
@@ -685,7 +752,9 @@ Do **not**:
|
|
|
685
752
|
- Replace `@tomorrowos/sdk` with a hand-rolled server
|
|
686
753
|
- Change the production start command away from `tsx server.ts` / `npm run start`
|
|
687
754
|
- Point Supabase at Replit’s reserved `DATABASE_URL` when `SUPABASE_URL` should be used
|
|
755
|
+
- List Q1 databases with **Replit PostgreSQL first** or mark it recommended instead of Supabase
|
|
688
756
|
- **Ask for `SUPABASE_URL` / the Postgres connection string more than once** (Secrets UI + chat, or again during execution / Publish)
|
|
757
|
+
- Ask the user to type `TOMORROWOS_STORE` or `DATABASE_SSL`
|
|
689
758
|
- Skip Cloudinary recommendation without stating the persistence tradeoff
|
|
690
759
|
- **Skip Cloudinary Secrets** after the user chooses Cloudinary — always collect `CLOUDINARY_*` inside Question 2 before Question 3
|
|
691
760
|
- **Announce “Question 2b”** or a separate follow-up question — show the Secrets form immediately instead
|
|
@@ -699,13 +768,13 @@ Do **not**:
|
|
|
699
768
|
- **Require** product name, colours, or logo in Question 3 — all branding fields are optional; missing → starter `brand.json` defaults
|
|
700
769
|
- **Re-ask** Question 3 for blank name/colour instead of keeping defaults
|
|
701
770
|
- Omit `[[ports]]` / `deploymentTarget` from `.replit` when setting up for Publish
|
|
702
|
-
- Run **
|
|
771
|
+
- Run **database connection tests**, **WebSocket console tests**, or other post-setup smoke tests unless Preview fails or the user asks
|
|
703
772
|
- **Debug or “fix” Supabase** because dev logs show `getaddrinfo ENOTFOUND` or `database connection failure` — save config and finish setup instead
|
|
704
|
-
- Ask how many screens / devices (≤5 vs >5)
|
|
773
|
+
- Ask how many screens / devices (≤5 vs >5)
|
|
705
774
|
|
|
706
775
|
---
|
|
707
776
|
|
|
708
|
-
## SQLite
|
|
777
|
+
## SQLite path — `server.ts` reference (Q1 option 3)
|
|
709
778
|
|
|
710
779
|
```ts
|
|
711
780
|
const store = createTomorrowOSStore({
|
|
@@ -741,7 +810,9 @@ TOMORROWOS_STORE=sqlite
|
|
|
741
810
|
|
|
742
811
|
## Protocol version
|
|
743
812
|
|
|
744
|
-
`replit-setup/1.
|
|
813
|
+
`replit-setup/1.10` — aligned with TomorrowOS protocol `1.0` and `@tomorrowos/sdk` store drivers `sqlite` | `supabase` | `postgres` | `memory`.
|
|
814
|
+
|
|
815
|
+
**Changelog 1.10:** Question 1 is a **database choice** with fixed order: **1) Supabase (Recommended) → 2) Built-in Replit PostgreSQL → 3) SQLite**. Supabase still collects `SUPABASE_URL` once only.
|
|
745
816
|
|
|
746
817
|
**Changelog 1.9:** Question 1 collects `SUPABASE_URL` **once only** (no second Secrets/chat prompt in execution). Question 3 branding fields are **all optional**; missing values keep starter `brand.json` defaults.
|
|
747
818
|
|
package/VERCEL_QUESTIONS.md
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
# Vercel / v0
|
|
1
|
+
# Vercel / v0 �?Verbatim question bank
|
|
2
2
|
|
|
3
|
-
> **Protocol:** `vercel-questions/1.0` (pairs with `VERCEL_SETUP.md` 1.9+ / `@tomorrowos/sdk` 0.9.
|
|
3
|
+
> **Protocol:** `vercel-questions/1.0` (pairs with `VERCEL_SETUP.md` 1.9+ / `@tomorrowos/sdk` 0.9.42+)
|
|
4
4
|
> **For Agents:** When asking the user a setup question, **copy-paste the block below for that step EXACTLY**.
|
|
5
|
-
> Do **not** paraphrase, reorder, rename options, or invent alternatives (no S3, no Supabase Storage, no “Blob recommended
|
|
5
|
+
> Do **not** paraphrase, reorder, rename options, or invent alternatives (no S3, no Supabase Storage, no “Blob recommended�? no “disable media�?.
|
|
6
6
|
> After each answer, configure per `VERCEL_SETUP.md`, then paste the **next** block.
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
## Q1
|
|
10
|
+
## Q1 �?Database (paste this entire block)
|
|
11
11
|
|
|
12
12
|
Which database should TomorrowOS use on Vercel?
|
|
13
13
|
|
|
14
|
-
**1. Supabase Postgres (recommended)**
|
|
14
|
+
**1. Supabase Postgres (recommended)** �?durable pairing/playlists; use the **Session pooler** URL (`*.pooler.supabase.com:6543`).
|
|
15
15
|
|
|
16
|
-
**2. Neon Postgres**
|
|
16
|
+
**2. Neon Postgres** �?serverless Postgres native to Vercel; use Neon’s **pooled** connection string from the Neon dashboard (not the direct un-pooled host for serverless).
|
|
17
17
|
|
|
18
|
-
**3. SQLite (`data/tomorrowos.db`)**
|
|
18
|
+
**3. SQLite (`data/tomorrowos.db`)** �?**demo / local only on Vercel.** The filesystem is ephemeral; pairings and playlists will not survive redeploys. Only choose this if you understand the limitation.
|
|
19
19
|
|
|
20
|
-
Reply with **1**, **2**, or **3** (or “Supabase
|
|
20
|
+
Reply with **1**, **2**, or **3** (or “Supabase�?/ “Neon�?/ “SQLite�?.
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
24
|
-
## After Q1
|
|
24
|
+
## After Q1 �?agent only (do not ask the user)
|
|
25
25
|
|
|
26
26
|
| Choice | You set silently | User only provides |
|
|
27
27
|
|--------|------------------|--------------------|
|
|
@@ -33,38 +33,38 @@ Never show blank Env fields for `TOMORROWOS_STORE` or `DATABASE_SSL`.
|
|
|
33
33
|
|
|
34
34
|
---
|
|
35
35
|
|
|
36
|
-
## Q2
|
|
36
|
+
## Q2 �?Media (paste this entire block)
|
|
37
37
|
|
|
38
38
|
How should playlist media (images/videos) be stored?
|
|
39
39
|
|
|
40
|
-
**1. Cloudinary (recommended)**
|
|
40
|
+
**1. Cloudinary (recommended)** �?durable public HTTPS URLs (`https://res.cloudinary.com/...`). Works out of the box with `@tomorrowos/sdk` auto-detection. **Prefer this on Vercel.**
|
|
41
41
|
|
|
42
|
-
**2. Vercel Blob**
|
|
42
|
+
**2. Vercel Blob** �?Vercel-native object storage; durable `https://*.public.blob.vercel-storage.com/...` URLs. Use when you want media on the same Vercel project without a Cloudinary account.
|
|
43
43
|
|
|
44
|
-
**3. Local disk only**
|
|
44
|
+
**3. Local disk only** �?`cms-panel/uploads` or `public/uploads` (OK for quick local tests; **not** for production Vercel fleets �?files are ephemeral).
|
|
45
45
|
|
|
46
|
-
Reply with **1**, **2**, or **3** (or “Cloudinary
|
|
46
|
+
Reply with **1**, **2**, or **3** (or “Cloudinary�?/ “Vercel Blob�?/ “local�?.
|
|
47
47
|
|
|
48
|
-
**Forbidden replacements (never ask these):** Vercel Blob as recommended #1; Supabase Storage; S3 / R2 / B2 / `MEDIA_S3_*`; “no media storage
|
|
48
|
+
**Forbidden replacements (never ask these):** Vercel Blob as recommended #1; Supabase Storage; S3 / R2 / B2 / `MEDIA_S3_*`; “no media storage�?/ disable uploads.
|
|
49
49
|
|
|
50
50
|
---
|
|
51
51
|
|
|
52
|
-
## Q3
|
|
52
|
+
## Q3 �?Brand (paste this entire block)
|
|
53
53
|
|
|
54
54
|
Let’s brand your TomorrowOS experience. Choose **one**:
|
|
55
55
|
|
|
56
|
-
**Option A
|
|
56
|
+
**Option A �?Website URL (recommended if you have a site)**
|
|
57
57
|
Paste **one public website URL**. I will use it **only** to fill **`brand.json`**: product name, tagline, primary / secondary / **background** / text colours, fonts, and logo.
|
|
58
|
-
I will **not** rebuild that website or add login
|
|
58
|
+
I will **not** rebuild that website or add login �?unless you explicitly ask for login/auth later.
|
|
59
59
|
|
|
60
|
-
**Option B
|
|
60
|
+
**Option B �?Manual brand fields**
|
|
61
61
|
Send as many of these as you can (name + at least one colour + logo is ideal):
|
|
62
62
|
1. **Product / venue name** (required)
|
|
63
63
|
2. **Tagline** (optional)
|
|
64
64
|
3. **Primary colour** (hex, e.g. `#FF8A3D`)
|
|
65
|
-
4. **Background colour** (hex
|
|
66
|
-
5. **Text colour** (hex, optional
|
|
65
|
+
4. **Background colour** (hex �?page / panel background)
|
|
66
|
+
5. **Text colour** (hex, optional �?default `#0A0908`)
|
|
67
67
|
6. **Secondary / accent colour** (hex, optional)
|
|
68
|
-
7. **Logo**
|
|
68
|
+
7. **Logo** �?upload SVG/PNG into the project, or a public image URL I can fetch into `./assets/`
|
|
69
69
|
|
|
70
70
|
Reply with a URL **or** the manual fields. Do not send only a name with no colours/logo unless you want defaults (I will confirm defaults before writing).
|