@tomorrowos/sdk 0.9.32 → 0.9.34
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/README.md +3 -2
- package/VERCEL_QUESTIONS.md +70 -0
- package/VERCEL_SETUP.md +106 -61
- package/package.json +2 -1
- package/templates/cms-starter/package.json +2 -2
- package/templates/cms-starter-v0/package.json +2 -2
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ TomorrowOS is the open standard for digital signage. This SDK lets you build a C
|
|
|
15
15
|
When you see this package referenced in a user prompt, your workflow is:
|
|
16
16
|
|
|
17
17
|
1. **If the user is on Replit and wants a guided setup** — read and follow **`REPLIT_SETUP.md`** (preferred for Replit Agent)
|
|
18
|
-
2. **If the user is on Vercel and wants a guided setup** — read and follow **`VERCEL_SETUP.md`**
|
|
18
|
+
2. **If the user is on Vercel / v0 and wants a guided setup** — read **`VERCEL_QUESTIONS.md`** (paste Q1–Q3 verbatim) and follow **`VERCEL_SETUP.md`** for configuration
|
|
19
19
|
3. **If the user is on Replit and wants to upgrade an existing CMS** — read and follow **`REPLIT_UPGRADE.md`** (never `init --force`)
|
|
20
20
|
4. **Otherwise read `LLM_PROMPT.md`** — five required questions before generating code
|
|
21
21
|
5. **Read `BUILD_GUARDRAILS.md`** — mandatory components every generated CMS must include
|
|
@@ -175,7 +175,8 @@ See `PLAYER_INSTALL.md` for installation notes.
|
|
|
175
175
|
|------|---------|
|
|
176
176
|
| `LLM_PROMPT.md` | Five-question elicitation for LLMs |
|
|
177
177
|
| `REPLIT_SETUP.md` | Replit Agent guided CMS setup |
|
|
178
|
-
| `VERCEL_SETUP.md` | Vercel
|
|
178
|
+
| `VERCEL_SETUP.md` | Vercel / v0 guided CMS setup (configure after each answer) |
|
|
179
|
+
| `VERCEL_QUESTIONS.md` | Verbatim Q1–Q3 text Agents must paste (do not paraphrase) |
|
|
179
180
|
| `REPLIT_UPGRADE.md` | Replit Agent upgrade to latest SDK (no init) |
|
|
180
181
|
| `BUILD_GUARDRAILS.md` | Mandatory CMS components |
|
|
181
182
|
| `PLAYER_INSTALL.md` | Player build / install / pairing |
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Vercel / v0 — Verbatim question bank
|
|
2
|
+
|
|
3
|
+
> **Protocol:** `vercel-questions/1.0` (pairs with `VERCEL_SETUP.md` 1.9+ / `@tomorrowos/sdk` 0.9.34+)
|
|
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”, no “disable media”).
|
|
6
|
+
> After each answer, configure per `VERCEL_SETUP.md`, then paste the **next** block.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Q1 — Database (paste this entire block)
|
|
11
|
+
|
|
12
|
+
Which database should TomorrowOS use on Vercel?
|
|
13
|
+
|
|
14
|
+
**1. Supabase Postgres (recommended)** — durable pairing/playlists; use the **Session pooler** URL (`*.pooler.supabase.com:6543`).
|
|
15
|
+
|
|
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
|
+
|
|
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
|
+
|
|
20
|
+
Reply with **1**, **2**, or **3** (or “Supabase” / “Neon” / “SQLite”).
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## After Q1 — agent only (do not ask the user)
|
|
25
|
+
|
|
26
|
+
| Choice | You set silently | User only provides |
|
|
27
|
+
|--------|------------------|--------------------|
|
|
28
|
+
| 1 Supabase | `TOMORROWOS_STORE=supabase`, `DATABASE_SSL=true` | `SUPABASE_URL` (pooler) |
|
|
29
|
+
| 2 Neon | `TOMORROWOS_STORE=postgres`, `DATABASE_SSL=true` | `DATABASE_URL` (pooled) |
|
|
30
|
+
| 3 SQLite | `TOMORROWOS_STORE=sqlite` | confirmation |
|
|
31
|
+
|
|
32
|
+
Never show blank Env fields for `TOMORROWOS_STORE` or `DATABASE_SSL`.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Q2 — Media (paste this entire block)
|
|
37
|
+
|
|
38
|
+
How should playlist media (images/videos) be stored?
|
|
39
|
+
|
|
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
|
+
|
|
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
|
+
|
|
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
|
+
|
|
46
|
+
Reply with **1**, **2**, or **3** (or “Cloudinary” / “Vercel Blob” / “local”).
|
|
47
|
+
|
|
48
|
+
**Forbidden replacements (never ask these):** Vercel Blob as recommended #1; Supabase Storage; S3 / R2 / B2 / `MEDIA_S3_*`; “no media storage” / disable uploads.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Q3 — Brand (paste this entire block)
|
|
53
|
+
|
|
54
|
+
Let’s brand your TomorrowOS experience. Choose **one**:
|
|
55
|
+
|
|
56
|
+
**Option A — Website URL (recommended if you have a site)**
|
|
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 — unless you explicitly ask for login/auth later.
|
|
59
|
+
|
|
60
|
+
**Option B — Manual brand fields**
|
|
61
|
+
Send as many of these as you can (name + at least one colour + logo is ideal):
|
|
62
|
+
1. **Product / venue name** (required)
|
|
63
|
+
2. **Tagline** (optional)
|
|
64
|
+
3. **Primary colour** (hex, e.g. `#FF8A3D`)
|
|
65
|
+
4. **Background colour** (hex — page / panel background)
|
|
66
|
+
5. **Text colour** (hex, optional — default `#0A0908`)
|
|
67
|
+
6. **Secondary / accent colour** (hex, optional)
|
|
68
|
+
7. **Logo** — upload SVG/PNG into the project, or a public image URL I can fetch into `./assets/`
|
|
69
|
+
|
|
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).
|
package/VERCEL_SETUP.md
CHANGED
|
@@ -5,7 +5,28 @@
|
|
|
5
5
|
>
|
|
6
6
|
> **On Vercel, this file is the setup questionnaire** (not `REPLIT_SETUP.md`, not `LLM_PROMPT.md`).
|
|
7
7
|
>
|
|
8
|
-
> Protocol id: `vercel-setup/1.
|
|
8
|
+
> Protocol id: `vercel-setup/1.9` — pairs with `@tomorrowos/sdk` **0.9.34+** (`templates/cms-starter-v0`, Fluid Functions WebSockets).
|
|
9
|
+
>
|
|
10
|
+
> **Questions source of truth:** `VERCEL_QUESTIONS.md` — Agents must **open that file and paste each Q block verbatim**. Do not paraphrase.
|
|
11
|
+
> **Copy questions verbatim from `VERCEL_QUESTIONS.md`.** Do not invent alternate Q2 options (no “Supabase Storage”, no S3, no “disable media”, no making Blob the recommended option).
|
|
12
|
+
> **`TOMORROWOS_STORE` and `DATABASE_SSL` are agent-only** — set them automatically after Q1; never put them in a user-facing Env form for the customer to type.
|
|
13
|
+
|
|
14
|
+
## NON-NEGOTIABLE VERCEL RUNTIME CONTRACT
|
|
15
|
+
|
|
16
|
+
The following rules are **mandatory acceptance criteria**, not suggestions. The Agent must preserve them throughout setup, Preview, Publish, fixes, and upgrades:
|
|
17
|
+
|
|
18
|
+
1. **One TomorrowOS instance only.** Use the shared instance exported through `api/index.ts`. **Never create a second `TomorrowOS` instance in `api/ws.ts`** or any other route.
|
|
19
|
+
2. **Never use `public/` as the Vercel Output Directory.** The dashboard Output Directory must be **empty / unset**. Serve the Control Panel at runtime from `cms-panel/` through TomorrowOS `staticRoot`.
|
|
20
|
+
3. **Preview may use Next only as an isolated reverse-proxy shell under `preview/`.** Preview must not replace TomorrowOS or determine the Production runtime.
|
|
21
|
+
4. **Publish must use the Fluid Function.** Production must run `api/index.ts` → the shared exported `http.Server`, with Fluid compute enabled. It must not use `next start`, a static export, or a bare `(req, res)` handler.
|
|
22
|
+
5. **After every Production deployment, verify all three gates before saying setup is complete:**
|
|
23
|
+
- `GET /status` returns TomorrowOS **JSON**, not HTML.
|
|
24
|
+
- `GET /` returns the TomorrowOS **Control Panel**.
|
|
25
|
+
- WebSocket upgrade on `/` or `/api` returns **`101 Switching Protocols`**, not `200` HTML.
|
|
26
|
+
6. **Pair devices only against the Production URL.** Do not instruct users to pair against v0 Preview or a local/internal URL.
|
|
27
|
+
7. If any gate fails, **fix and redeploy**. Never describe a deployment as successful based only on the Control Panel loading.
|
|
28
|
+
|
|
29
|
+
These rules override any platform-generated recommendation that conflicts with them.
|
|
9
30
|
|
|
10
31
|
## User trigger (copy-paste)
|
|
11
32
|
|
|
@@ -13,15 +34,11 @@ When a human pastes a prompt like this, **read this file and start Question 1 im
|
|
|
13
34
|
|
|
14
35
|
```text
|
|
15
36
|
Follow @tomorrowos/sdk VERCEL_SETUP.md and set up my TomorrowOS CMS.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Use Next.js only as a v0/Preview shell with a reverse proxy; Production Publish must remain pure Node TomorrowOS.listen (not Next).
|
|
22
|
-
Before claiming Publish works: Framework Preset must be Other/null (not Next.js), Fluid on, GET /status on the production URL must return JSON (not HTML), GET / must return the Control Panel, and WebSocket upgrade on / or /api must return 101 (not 200 HTML).
|
|
23
|
-
Do not put startCommand or processes in vercel.json (v0 schema rejects them).
|
|
24
|
-
Use cms-starter-v0 layout: cms-app.ts + api/index.ts (export default server) + cms-panel/ + rewrites to /api. Do not create a second TomorrowOS instance in api/ws.ts.
|
|
37
|
+
First open VERCEL_QUESTIONS.md. For Q1, Q2, Q3: paste each question block VERBATIM (character-for-character). Do not rephrase options.
|
|
38
|
+
Q2 must show Cloudinary (recommended) as option 1 — never Blob-as-recommended, never S3, never Supabase Storage.
|
|
39
|
+
After database choice, YOU set TOMORROWOS_STORE and DATABASE_SSL — do not ask me to fill those.
|
|
40
|
+
Do not use LLM_PROMPT.md or REPLIT_SETUP.md. No OpenAI/LLM API keys.
|
|
41
|
+
Apply the NON-NEGOTIABLE VERCEL RUNTIME CONTRACT exactly: one TomorrowOS instance; no public/ Output Directory; Preview Next only under preview/; Publish through the Fluid Function; verify /status JSON, / Control Panel, and WebSocket 101; pair devices only with the Production URL.
|
|
25
42
|
```
|
|
26
43
|
|
|
27
44
|
Alternate triggers:
|
|
@@ -128,30 +145,43 @@ v0 Preview is often a **Next.js runtime** hardwired to `next dev`. A raw `tsx se
|
|
|
128
145
|
|
|
129
146
|
## Questionnaire scope (STRICT)
|
|
130
147
|
|
|
131
|
-
Ask **only** these questions, in **this exact order
|
|
148
|
+
Ask **only** these questions, in **this exact order**. **Copy the “Ask exactly” blocks verbatim** — do not paraphrase options.
|
|
132
149
|
|
|
133
150
|
| Step | Section | When |
|
|
134
151
|
|------|---------|------|
|
|
135
152
|
| 1 | **Question 1** — Database (Supabase → Neon → SQLite) | Always |
|
|
136
|
-
| 2 | **Question 2** — Media
|
|
153
|
+
| 2 | **Question 2** — Media (**Cloudinary recommended** → Vercel Blob → local) | Always (after Q1) |
|
|
137
154
|
| 3 | **Question 3** — Brand / TomorrowOS look (`brand.json` only) | Always last |
|
|
138
155
|
|
|
139
156
|
**That is the complete list.** Do **not** ask how many screens / devices.
|
|
140
157
|
|
|
158
|
+
**Forbidden invented Question 2 options (never offer these in chat or UI):**
|
|
159
|
+
|
|
160
|
+
- ❌ “Vercel Blob **(recommended)**” as option 1 — Blob is option **2**, not recommended over Cloudinary
|
|
161
|
+
- ❌ “Supabase Storage” / S3 bucket / `SUPABASE_SERVICE_ROLE_KEY` for media
|
|
162
|
+
- ❌ “No media storage” / “disable media uploads” / “remote URLs only” as a numbered choice
|
|
163
|
+
- ❌ Any media list that does not start with **Cloudinary (recommended)**
|
|
164
|
+
|
|
165
|
+
**Forbidden Env UX after Question 1:**
|
|
166
|
+
|
|
167
|
+
- ❌ Showing the user empty fields for `TOMORROWOS_STORE` or `DATABASE_SSL` to fill
|
|
168
|
+
- ❌ Asking in chat “what should TOMORROWOS_STORE be?”
|
|
169
|
+
- ✅ After DB choice + URL paste: **you** write those two vars silently (see Q1 Steps B/C/D)
|
|
170
|
+
|
|
141
171
|
**Forbidden extra questions (never ask, even if the user skips a step):**
|
|
142
172
|
|
|
143
173
|
- ❌ OpenAI / Anthropic / Gemini / any LLM API key (`sk-…`, etc.)
|
|
144
174
|
- ❌ “AI pairing”, “AI feature logic”, or inventing auth that needs an LLM key
|
|
145
|
-
- ❌ Asking the user to type `TOMORROWOS_STORE` or `DATABASE_SSL`
|
|
175
|
+
- ❌ Asking the user to type `TOMORROWOS_STORE` or `DATABASE_SSL`
|
|
146
176
|
- ❌ Any secret not listed in Questions 1–3 (DB URL, media credentials, brand)
|
|
147
177
|
|
|
148
178
|
TomorrowOS pairing and Control Panel logic live in `@tomorrowos/sdk`. They do **not** call OpenAI.
|
|
149
179
|
|
|
150
|
-
If the user **skips** a Question 2 option, do **not** invent a substitute question. Re-state Question 2 choices
|
|
180
|
+
If the user **skips** a Question 2 option, do **not** invent a substitute question. Re-state Question 2 choices **verbatim**, or proceed with local uploads + warning — never pivot to LLM keys or Supabase Storage.
|
|
151
181
|
|
|
152
182
|
If the user says “just set it up, don’t ask questions,” respond:
|
|
153
183
|
|
|
154
|
-
> I need a few quick answers from VERCEL_SETUP.md (database — Supabase or Neon preferred — media storage, and branding). It takes about a minute and ensures the CMS works on Vercel.
|
|
184
|
+
> I need a few quick answers from VERCEL_SETUP.md (database — Supabase or Neon preferred — media storage with Cloudinary recommended, and branding). It takes about a minute and ensures the CMS works on Vercel.
|
|
155
185
|
|
|
156
186
|
Then ask **Question 1**.
|
|
157
187
|
|
|
@@ -159,26 +189,26 @@ Then ask **Question 1**.
|
|
|
159
189
|
|
|
160
190
|
## Hard rules
|
|
161
191
|
|
|
162
|
-
1. **
|
|
163
|
-
2. **
|
|
164
|
-
3. **
|
|
165
|
-
4. **
|
|
166
|
-
5. **
|
|
167
|
-
6. **
|
|
168
|
-
7. **
|
|
169
|
-
8. **
|
|
170
|
-
9. **
|
|
171
|
-
10. **
|
|
172
|
-
11. **
|
|
173
|
-
12. **
|
|
174
|
-
13.
|
|
175
|
-
14. **
|
|
176
|
-
15.
|
|
177
|
-
16. **
|
|
178
|
-
17. **
|
|
179
|
-
18. **
|
|
180
|
-
|
|
181
|
-
**Question order:** Q1 → Q2 → Q3 → execution checklist.
|
|
192
|
+
1. **Open `VERCEL_QUESTIONS.md` first.** Paste Q1 → configure → paste Q2 → configure → paste Q3. Never paraphrase question options. Never use `LLM_PROMPT.md` or `REPLIT_SETUP.md` as the questionnaire. **Never** ask for OpenAI or other LLM API keys.
|
|
193
|
+
2. **Question 2 options are fixed:** (1) Cloudinary **(recommended)**, (2) Vercel Blob, (3) local disk. Do not reorder; do not invent Supabase Storage / disable-uploads.
|
|
194
|
+
3. **Cloudinary:** open **one** Vercel Env popup with **all** Cloudinary fields together. Do **not** quiz one credential at a time.
|
|
195
|
+
4. **`TOMORROWOS_STORE` + `DATABASE_SSL` = agent-owned.** After Q1 choice (and URL if needed), set them yourself in Vercel Env Vars. **Never** include them as blank fields for the customer. Mapping: Supabase → `TOMORROWOS_STORE=supabase` + `DATABASE_SSL=true`; Neon → `TOMORROWOS_STORE=postgres` + `DATABASE_SSL=true`; SQLite → `TOMORROWOS_STORE=sqlite` (no `DATABASE_SSL` required).
|
|
196
|
+
5. **Do not invent** Cloudinary credentials, database URLs, Vercel Blob tokens, brand colours, **or LLM API keys**.
|
|
197
|
+
6. **Postgres env naming:** prefer **`SUPABASE_URL`** for Supabase; prefer **`DATABASE_URL`** for Neon.
|
|
198
|
+
7. **Always prefer pooled connection strings** (Supabase Session pooler **6543**; Neon pooled host).
|
|
199
|
+
8. **Prefer `npx @tomorrowos/sdk init --hosting v0`**. For Replit/Railway use default `init`. Do not rebuild pairing / WebSocket APIs.
|
|
200
|
+
9. **Never commit secrets.** Use Vercel Environment Variables.
|
|
201
|
+
10. **Skip Replit-only files.**
|
|
202
|
+
11. **SQLite is not a production store on Vercel.**
|
|
203
|
+
12. **Enable Fluid compute** for Production WebSockets.
|
|
204
|
+
13. **Production:** `api/index.ts` exports `http.Server` from `TomorrowOS.listen`. Not `next start`. No second TomorrowOS in `api/ws.ts`.
|
|
205
|
+
14. **Preview:** Next reverse-proxy shell when v0 is Next-hardwired.
|
|
206
|
+
15. After Q&A: **configure → install → deploy → minimal verify**.
|
|
207
|
+
16. **No inventing CMS login** from a branding URL.
|
|
208
|
+
17. **Skip ≠ invent.** Stay on Q1–Q3 only.
|
|
209
|
+
18. **Publish gate:** `/status` JSON + WebSocket 101; no static `public/` trap.
|
|
210
|
+
|
|
211
|
+
**Question order:** Q1 → (auto-set store env) → Q2 → Q3 → execution checklist.
|
|
182
212
|
|
|
183
213
|
---
|
|
184
214
|
|
|
@@ -554,7 +584,18 @@ If Vercel’s UI and this file disagree on bundling, **prefer whatever keeps a s
|
|
|
554
584
|
|
|
555
585
|
## Question 1 — Database (always)
|
|
556
586
|
|
|
557
|
-
> **Do not** ask screen counts. Present all three options; recommend **Supabase** for Vercel fleets.
|
|
587
|
+
> **Do not** ask screen counts. Present all three options; recommend **Supabase** for Vercel fleets.
|
|
588
|
+
> **After the user picks a database:** collect the URL if needed, then **you** set `TOMORROWOS_STORE` + `DATABASE_SSL` (see mapping below). The customer must **never** be asked to type those two names or values.
|
|
589
|
+
|
|
590
|
+
### Agent-owned env mapping (mandatory)
|
|
591
|
+
|
|
592
|
+
| User chose | You set (silently) | User only provides |
|
|
593
|
+
|------------|--------------------|--------------------|
|
|
594
|
+
| 1 Supabase | `TOMORROWOS_STORE=supabase`, `DATABASE_SSL=true` | `SUPABASE_URL` (pooler string) |
|
|
595
|
+
| 2 Neon | `TOMORROWOS_STORE=postgres`, `DATABASE_SSL=true` | `DATABASE_URL` (pooled string) |
|
|
596
|
+
| 3 SQLite | `TOMORROWOS_STORE=sqlite` | Confirmation only |
|
|
597
|
+
|
|
598
|
+
If you open an Env configuration UI for Q1, fields visible to the user may include **only** `SUPABASE_URL` or `DATABASE_URL`. **Do not** show blank `TOMORROWOS_STORE` / `DATABASE_SSL` inputs — write those yourself in the same step.
|
|
558
599
|
|
|
559
600
|
### Step A — Ask storage choice
|
|
560
601
|
|
|
@@ -572,9 +613,9 @@ If Vercel’s UI and this file disagree on bundling, **prefer whatever keeps a s
|
|
|
572
613
|
|
|
573
614
|
### Step B — If **1 / Supabase**
|
|
574
615
|
|
|
575
|
-
**Ask exactly (connection string only):**
|
|
616
|
+
**Ask exactly (connection string only — not TOMORROWOS_STORE / DATABASE_SSL):**
|
|
576
617
|
|
|
577
|
-
> Paste your Supabase Postgres connection string. I will store it as **`SUPABASE_URL`**.
|
|
618
|
+
> Paste your Supabase Postgres connection string. I will store it as **`SUPABASE_URL`**. I will set **`TOMORROWOS_STORE`** and **`DATABASE_SSL`** for you automatically.
|
|
578
619
|
>
|
|
579
620
|
> In Supabase: **Project Settings → Database → Connection string → Connection pooling** (Session mode).
|
|
580
621
|
> Preferred shape:
|
|
@@ -582,36 +623,36 @@ If Vercel’s UI and this file disagree on bundling, **prefer whatever keeps a s
|
|
|
582
623
|
>
|
|
583
624
|
> **Do not** use the direct host `db.*.supabase.co:5432` for Vercel.
|
|
584
625
|
|
|
585
|
-
**You must then (automatic — do NOT ask the user to type
|
|
626
|
+
**You must then (automatic — do NOT ask the user to type store/ssl vars):**
|
|
586
627
|
|
|
587
|
-
1. Set Vercel Env Vars:
|
|
588
|
-
- `SUPABASE_URL=<user pooler string>`
|
|
589
|
-
- `TOMORROWOS_STORE=supabase` ← **
|
|
590
|
-
- `DATABASE_SSL=true` ← **
|
|
591
|
-
2. Wire `server.ts` as in **Runtime & Vercel deploy rules**.
|
|
628
|
+
1. Set Vercel Env Vars in one step:
|
|
629
|
+
- `SUPABASE_URL=<user pooler string>` ← from user
|
|
630
|
+
- `TOMORROWOS_STORE=supabase` ← **you set; never ask**
|
|
631
|
+
- `DATABASE_SSL=true` ← **you set; never ask**
|
|
632
|
+
2. Wire `cms-app.ts` / `server.ts` store as in **Runtime & Vercel deploy rules**.
|
|
592
633
|
3. Optional committed `.env.example` with **placeholders only**.
|
|
593
634
|
4. **Do not** commit the real connection string.
|
|
594
|
-
5. **Do not** open a
|
|
635
|
+
5. **Do not** open a form whose blank fields include `TOMORROWOS_STORE` or `DATABASE_SSL`.
|
|
595
636
|
|
|
596
637
|
### Step C — If **2 / Neon**
|
|
597
638
|
|
|
598
639
|
**Ask exactly (connection string only):**
|
|
599
640
|
|
|
600
|
-
> Paste your **Neon pooled** Postgres connection string. I will store it as **`DATABASE_URL`**.
|
|
641
|
+
> Paste your **Neon pooled** Postgres connection string. I will store it as **`DATABASE_URL`**. I will set **`TOMORROWOS_STORE`** and **`DATABASE_SSL`** for you automatically.
|
|
601
642
|
>
|
|
602
643
|
> In Neon: **Dashboard → Connection details → Pooled connection**.
|
|
603
644
|
> Typical shape:
|
|
604
645
|
> `postgresql://[user]:[password]@[endpoint]-pooler.[region].aws.neon.tech/[dbname]?sslmode=require`
|
|
605
646
|
|
|
606
|
-
**You must then (automatic
|
|
647
|
+
**You must then (automatic):**
|
|
607
648
|
|
|
608
649
|
1. Set Vercel Env Vars:
|
|
609
|
-
- `DATABASE_URL=<user pooled string>`
|
|
610
|
-
- `TOMORROWOS_STORE=postgres` ← **
|
|
611
|
-
- `DATABASE_SSL=true` ← **
|
|
612
|
-
2. Wire `
|
|
650
|
+
- `DATABASE_URL=<user pooled string>` ← from user
|
|
651
|
+
- `TOMORROWOS_STORE=postgres` ← **you set; never ask**
|
|
652
|
+
- `DATABASE_SSL=true` ← **you set; never ask**
|
|
653
|
+
2. Wire `createTomorrowOSStore` for Postgres.
|
|
613
654
|
3. **Do not** commit the real connection string.
|
|
614
|
-
4. **Do not** ask the user to fill `TOMORROWOS_STORE` or `DATABASE_SSL` in chat or
|
|
655
|
+
4. **Do not** ask the user to fill `TOMORROWOS_STORE` or `DATABASE_SSL` in chat or Env UI.
|
|
615
656
|
5. If you see `ENETUNREACH` on `:5432`, switch to Neon’s **pooled** URL.
|
|
616
657
|
|
|
617
658
|
### Step D — If **3 / SQLite**
|
|
@@ -625,7 +666,7 @@ Only proceed after the user explicitly confirms.
|
|
|
625
666
|
**You must then (automatic):**
|
|
626
667
|
|
|
627
668
|
1. Set `TOMORROWOS_STORE=sqlite` yourself (do not ask the user to type it).
|
|
628
|
-
2. Keep `sqlitePath`
|
|
669
|
+
2. Keep `sqlitePath` for `data/tomorrowos.db`.
|
|
629
670
|
3. Warn again in the final summary that they should move to Supabase or Neon for real devices.
|
|
630
671
|
|
|
631
672
|
**Later in Question 3:** set `cms.hostingTarget` to **`"vercel"`** (all Q1 branches).
|
|
@@ -635,22 +676,25 @@ Only proceed after the user explicitly confirms.
|
|
|
635
676
|
## Question 2 — Media storage
|
|
636
677
|
|
|
637
678
|
> **This question is only about media files (images/videos).**
|
|
638
|
-
> It is **not** about OpenAI, AI pairing, or LLM keys. If you are about to ask for an `sk-` key, **stop** — you are off-protocol.
|
|
679
|
+
> It is **not** about OpenAI, AI pairing, or LLM keys. If you are about to ask for an `sk-` key, **stop** — you are off-protocol.
|
|
680
|
+
> **Copy the three options below verbatim.** Wrong examples that must **never** appear: “Vercel Blob (recommended)”, “Supabase Storage”, “No media storage / disable uploads”.
|
|
639
681
|
|
|
640
682
|
### Step A — Ask storage choice
|
|
641
683
|
|
|
642
|
-
**Ask exactly:**
|
|
684
|
+
**Ask exactly (wording must match — Cloudinary is recommended):**
|
|
643
685
|
|
|
644
686
|
> How should playlist media (images/videos) be stored?
|
|
645
687
|
>
|
|
646
|
-
> **1. Cloudinary (recommended)** — durable public HTTPS URLs (`https://res.cloudinary.com/...`). Works out of the box with `@tomorrowos/sdk` auto-detection.
|
|
688
|
+
> **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.**
|
|
647
689
|
>
|
|
648
|
-
> **2. Vercel Blob** — Vercel-native object storage; durable `https://*.public.blob.vercel-storage.com/...` URLs.
|
|
690
|
+
> **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.
|
|
649
691
|
>
|
|
650
|
-
> **3. Local disk only** — `public/uploads` (OK for quick local tests; **not** for production Vercel fleets — files are ephemeral).
|
|
692
|
+
> **3. Local disk only** — `cms-panel/uploads` or `public/uploads` (OK for quick local tests; **not** for production Vercel fleets — files are ephemeral).
|
|
651
693
|
>
|
|
652
694
|
> Reply with **1**, **2**, or **3** (or “Cloudinary” / “Vercel Blob” / “local”).
|
|
653
695
|
|
|
696
|
+
If you catch yourself about to offer Blob-as-recommended, Supabase Storage, or “no media”, **stop and paste the block above instead**.
|
|
697
|
+
|
|
654
698
|
### Step B — If **1 / Cloudinary** (same Question 2 — **one Env popup**)
|
|
655
699
|
|
|
656
700
|
> **Critical UX rule:** Immediately open the **Vercel Environment Variables configuration popup / form** with **all Cloudinary fields in one UI**. Do **not** ask for cloud name, then key, then secret in separate chat messages.
|
|
@@ -837,8 +881,8 @@ Then (**Scheme A — mandatory for Publish**):
|
|
|
837
881
|
|------|----------|--------------|
|
|
838
882
|
| `SUPABASE_URL` | If Q1 = Supabase | User pastes URL |
|
|
839
883
|
| `DATABASE_URL` | If Q1 = Neon | User pastes URL |
|
|
840
|
-
| `TOMORROWOS_STORE` | Yes | **Agent auto-sets** (`supabase` / `postgres` / `sqlite`) |
|
|
841
|
-
| `DATABASE_SSL` | Yes for Postgres | **Agent auto-sets** `true` |
|
|
884
|
+
| `TOMORROWOS_STORE` | Yes | **Agent auto-sets only** — never a blank field for the user (`supabase` / `postgres` / `sqlite`) |
|
|
885
|
+
| `DATABASE_SSL` | Yes for Postgres | **Agent auto-sets only** — never a blank field for the user (`true`) |
|
|
842
886
|
| `CLOUDINARY_*` | If Q2 = Cloudinary | User via **one Env popup** (all fields) |
|
|
843
887
|
| `BLOB_READ_WRITE_TOKEN` | If Q2 = Vercel Blob | User / Blob link |
|
|
844
888
|
| `TOMORROWOS_INTERNAL_PORT` | Preview only | Agent (e.g. `3001`) |
|
|
@@ -920,7 +964,8 @@ Tell the user:
|
|
|
920
964
|
| Blob uploads 401 / missing token | Blob not linked | Vercel Storage → Blob + `BLOB_READ_WRITE_TOKEN` |
|
|
921
965
|
| WebSocket fails on Publish | Fluid off / static-only / Next as Production / no Function WS | Enable Fluid; Scheme A; test 101 upgrade |
|
|
922
966
|
| Devices fail only on Preview | Next proxy cannot upgrade `wss` | Expected — pair on Publish URL |
|
|
923
|
-
| Agent asked user to fill `TOMORROWOS_STORE` / `DATABASE_SSL` | Off-protocol | Agent must auto-set
|
|
967
|
+
| Agent asked user to fill `TOMORROWOS_STORE` / `DATABASE_SSL` | Off-protocol | Agent must auto-set after DB choice; remove those fields from user Env forms |
|
|
968
|
+
| Agent offered Blob-as-recommended / Supabase Storage / “no media” for Q2 | Invented options | Re-ask Q2 verbatim: **1 Cloudinary (recommended)**, 2 Blob, 3 local |
|
|
924
969
|
| Agent asked Cloudinary key/secret in three chat turns | Off-protocol | Use **one Env popup** with all Cloudinary fields |
|
|
925
970
|
| Agent asked for OpenAI / `sk-` key during setup | Hallucinated “AI pairing” requirement | **Refuse.** TomorrowOS does not need LLM keys. Return to Q2 media choices only |
|
|
926
971
|
| Agent built a login page after user pasted a URL | Misread brand reference as product scope | Remove login; keep starter Control Panel; apply URL only to `brand.json` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomorrowos/sdk",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.34",
|
|
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",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"LLM_PROMPT.md",
|
|
22
22
|
"REPLIT_SETUP.md",
|
|
23
23
|
"VERCEL_SETUP.md",
|
|
24
|
+
"VERCEL_QUESTIONS.md",
|
|
24
25
|
"REPLIT_UPGRADE.md",
|
|
25
26
|
"BUILD_GUARDRAILS.md",
|
|
26
27
|
"PLAYER_INSTALL.md",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "my-cms",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.34",
|
|
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.9.
|
|
16
|
+
"@tomorrowos/sdk": "^0.9.34",
|
|
17
17
|
"dotenv": "^17.2.3",
|
|
18
18
|
"tsx": "^4.19.0"
|
|
19
19
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "my-cms",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.34",
|
|
4
4
|
"description": "TomorrowOS CMS for Vercel / v0 Publish (Fluid Function + WebSockets + optional Next Preview).",
|
|
5
5
|
"private": true,
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"build-player": "tomorrowos build --platform tizen"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@tomorrowos/sdk": "^0.9.
|
|
20
|
+
"@tomorrowos/sdk": "^0.9.34",
|
|
21
21
|
"dotenv": "^17.2.3",
|
|
22
22
|
"tsx": "^4.19.0"
|
|
23
23
|
},
|