@tomorrowos/sdk 0.9.26 → 0.9.28

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 CHANGED
@@ -73,7 +73,7 @@ IF any step contradicts Vercel, adapt to settings that Vercel can accept.
73
73
 
74
74
  That wizard asks: database (**Supabase** → **Neon** → SQLite demo), media (**Cloudinary** → **Vercel Blob** → local),
75
75
  branding (manual fields or **website URL → `brand.json` only**, no login unless asked). Preview may use a thin **Next.js reverse proxy**;
76
- **Publish stays pure Node** `TomorrowOS.listen` (Framework Preset = Other gate on no `404 NOT_FOUND`). Cloudinary uses **one Env popup** (all fields).
76
+ **Publish stays pure Node** `TomorrowOS.listen` (Scheme A: root `server.ts`, Next in `preview/`, `GET /status` must be JSON). Cloudinary uses **one Env popup** (all fields).
77
77
  Neon/Supabase: agent auto-sets `TOMORROWOS_STORE` + `DATABASE_SSL`. Sets `cms.hostingTarget` to `"vercel"`.
78
78
 
79
79
  ### Replit upgrade (existing CMS)
package/VERCEL_SETUP.md CHANGED
@@ -5,7 +5,7 @@
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.5` — pairs with `@tomorrowos/sdk` packages that ship `templates/cms-starter` and this file.
8
+ > Protocol id: `vercel-setup/1.7` — pairs with `@tomorrowos/sdk` packages that ship `templates/cms-starter` and this file.
9
9
 
10
10
  ## User trigger (copy-paste)
11
11
 
@@ -19,7 +19,8 @@ If any step contradicts Vercel, adapt to settings Vercel can accept (document th
19
19
  After all setup questions are answered (including Cloudinary or Vercel Blob Env Vars if you chose those), configure and deploy — minimal verification only (Control Panel at /). Prefer Supabase Session pooler URL or Neon pooled URL. Do not treat sandbox ENETUNREACH / IPv6 :5432 errors as a hard setup failure when a pooler URL is configured for production.
20
20
  Question 3 only updates brand.json from colours/logo/name (a website URL is brand reference only — do not add CMS login/auth unless the user explicitly asks). Do not skip steps.
21
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), startCommand must run TomorrowOS Node, and GET / on the production URL must return the Control Panel (not 404 NOT_FOUND).
22
+ Before claiming Publish works: Framework Preset must be Other/null (not Next.js), package.json `start` must run TomorrowOS Node, GET /status on the production URL must return JSON (not HTML), and GET / must return the Control Panel (not 404 NOT_FOUND).
23
+ Do not put startCommand or processes in vercel.json (v0 schema rejects them). Do not move server.ts into api/.
23
24
  ```
24
25
 
25
26
  Alternate triggers:
@@ -82,6 +83,29 @@ almost always means **Vercel still thinks this is a Next.js / static deploy**, n
82
83
 
83
84
  **Setup is NOT complete** while Production `GET /` returns `404: NOT_FOUND`. Fix Framework Preset + Start Command and redeploy.
84
85
 
86
+ ### Publish static trap — `public/` served without Node (read this)
87
+
88
+ A common **worse** failure mode than `404: NOT_FOUND`:
89
+
90
+ - `GET /` loads the Control Panel HTML (from static `public/index.html`)
91
+ - `GET /status`, `/devices`, etc. return **HTML** (Vercel 404 page)
92
+ - The panel shows **CMS unreachable** and console:
93
+ `Unexpected token 'T', "The page c"... is not valid JSON`
94
+
95
+ **Root cause:** Vercel deployed `public/` as a **static site** (Output Directory = `public` or Framework=Other default *“public if it exists”*). **No Node process** is running `tsx server.ts`, so API routes never hit `TomorrowOS`.
96
+
97
+ **Fix (Scheme A — see dedicated section below):** force Vercel to run the **root `server.ts` Node entry** with Fluid. `public/` must be served **at runtime** via `staticRoot` in `listen()`, **not** as the build output directory.
98
+
99
+ **Publish gate (mandatory):** after deploy, `GET /status` must return **JSON** starting with `{`, not HTML starting with `<` or `The page`.
100
+
101
+ ```bash
102
+ curl -s https://YOUR-PROJECT.vercel.app/status | head -c 80
103
+ # Expected: {"status":"success",...}
104
+ # Failure: The page could not be found OR <!DOCTYPE html>
105
+ ```
106
+
107
+ **Setup is NOT complete** while `/status` returns HTML or the panel shows the JSON parse error.
108
+
85
109
  ### Preview (v0 / Vercel Agent sandbox) — Next.js shell allowed
86
110
 
87
111
  v0 Preview is often a **Next.js runtime** hardwired to `next dev`. A raw `tsx server.ts` may listen successfully while Preview still shows a blank page, because the sandbox intercepts the public port with Next before requests reach TomorrowOS.
@@ -150,12 +174,175 @@ Then ask **Question 1**.
150
174
  14. **No inventing CMS login.** A branding URL never means “build auth.” Only add login if the user **explicitly** requests it.
151
175
  15. **Skip ≠ invent.** If the user skips media choice or a credential, do not replace it with OpenAI/auth/login questions. Stay on Q1–Q3 only.
152
176
  16. **Neon / Supabase helpers are agent-owned.** After the user pastes the DB URL, **you** set `TOMORROWOS_STORE` and `DATABASE_SSL` automatically — **do not** ask the user to fill those two.
153
- 17. **Publish gate:** do not mark setup complete while Production returns `404: NOT_FOUND`. Fix Framework Preset + Start Command first (see **Publish 404** section).
177
+ 17. **Publish gate:** do not mark setup complete while Production returns `404: NOT_FOUND` **or** `/status` returns HTML (static `public/` trap).
178
+ 18. **Scheme A is doc-driven:** achieve Production Node Publish by **project layout + `vercel.json` + dashboard settings** during setup — **no SDK code changes** required (see **Scheme A** section).
154
179
 
155
180
  **Question order:** Q1 → Q2 → Q3 → execution checklist.
156
181
 
157
182
  ---
158
183
 
184
+ ## Scheme A — Standard Node Publish (mandatory for Production)
185
+
186
+ > **Goal:** Preview may use Next + proxy; **Publish** runs **only** root `server.ts` + `TomorrowOS.listen` on Vercel Fluid.
187
+ > **Scope:** This section is implemented entirely during setup (move files, write `vercel.json`, patch dashboard). **Do not** change `@tomorrowos/sdk` source.
188
+
189
+ ### Why Scheme A exists
190
+
191
+ | Layer | Preview (v0) | Publish (Production) |
192
+ |-------|----------------|----------------------|
193
+ | Host | Next.js shell + HTTP proxy | **Node `server.ts`** only |
194
+ | `public/` | Proxied from TomorrowOS | Served by **`staticRoot`** inside `listen()` — **not** as Vercel Output Directory |
195
+ | WebSocket | Optional / may fail in Preview | Required on same origin (`wss://`) |
196
+ | Next files | Allowed under `preview/` | **Must not** live at project root |
197
+
198
+ ### A1 — Project layout (Agent must enforce)
199
+
200
+ **At project root (Production):**
201
+
202
+ ```
203
+ server.ts ← REQUIRED name at root (or server.mts)
204
+ vercel.json
205
+ package.json
206
+ brand.json
207
+ public/ ← CMS static UI; NOT the Vercel output directory
208
+ ```
209
+
210
+ **Preview only (when v0 needs Next) — move ALL of these under `preview/`:**
211
+
212
+ ```
213
+ preview/
214
+ next.config.mjs
215
+ app/ ← Next proxy routes
216
+ postcss.config.mjs
217
+ next-env.d.ts
218
+ tsconfig.json ← Next/tsconfig if separate from server
219
+ ```
220
+
221
+ **Remove from project root after move:** `next.config.mjs`, `app/`, root Next `tsconfig` plugin config, `postcss.config.mjs`, `next-env.d.ts`.
222
+
223
+ **Do NOT:**
224
+
225
+ - ❌ Leave `next.config.mjs` + `app/` at root while claiming Production is Node-only
226
+ - ❌ Create root `api/index.ts` exporting `http.Server` + `routes` catch-all
227
+ - ❌ Set Output Directory to `public` or `.`
228
+
229
+ **Update `package.json` scripts when Preview uses `preview/`:**
230
+
231
+ ```json
232
+ {
233
+ "scripts": {
234
+ "dev": "tsx watch server.ts",
235
+ "dev:preview": "concurrently -k \"npm:dev:tomorrowos\" \"npm:dev:next\"",
236
+ "dev:tomorrowos": "cross-env TOMORROWOS_INTERNAL_PORT=3001 tsx watch server.ts",
237
+ "dev:next": "cd preview && next dev -p 3000",
238
+ "start": "tsx server.ts",
239
+ "build": "node -e \"process.exit(0)\""
240
+ }
241
+ }
242
+ ```
243
+
244
+ ### A2 — `server.ts` entry (Vercel zero-config Node detection)
245
+
246
+ Vercel detects a **root** `server.ts` / `server.mts` and routes traffic to it when:
247
+
248
+ 1. The file lives at **project root** (not only under `api/`)
249
+ 2. **`listen()` runs at module load** (top-level, not inside an unexported function)
250
+ 3. The file **`export default server`** (the `http.Server` from `tomorrowos.listen`)
251
+
252
+ Use the pattern in **Runtime & Vercel deploy rules** below. On Publish, **do not** set `TOMORROWOS_INTERNAL_PORT` — let Vercel inject `PORT`.
253
+
254
+ ### A3 — `vercel.json` (Production)
255
+
256
+ **v0 / `.v0/vercel.deploy.json` schema:** only a **minimal** object is valid. These keys are **rejected** — never add them:
257
+
258
+ - ❌ `startCommand`
259
+ - ❌ `processes`
260
+ - ❌ `routes` / `rewrites` to fake API routing
261
+ - ❌ `outputDirectory: "public"` or `"."`
262
+
263
+ Vercel discovers the start command from **`package.json` → `"start": "tsx server.ts"`**, not from `vercel.json`.
264
+
265
+ ```json
266
+ {
267
+ "fluid": true,
268
+ "framework": null,
269
+ "installCommand": "npm install",
270
+ "buildCommand": "npm run build"
271
+ }
272
+ ```
273
+
274
+ Use `pnpm` / `yarn` equivalents if the project uses them.
275
+
276
+ **Critical:**
277
+
278
+ - **Do not** add `startCommand` to `vercel.json` (invalid in v0; redundant on full Vercel — use `package.json` `start`)
279
+ - **Do not** set `outputDirectory` to `public` or `.`
280
+ - `"buildCommand"` must run the no-op `npm run build` — **never** `next build` for Production
281
+ - Set **Output Directory empty** in the **Vercel dashboard** (Scheme A4) — that is where static-vs-Node is decided, not via invalid `vercel.json` keys
282
+
283
+ ### A4 — Vercel Project Settings (dashboard or API — mandatory)
284
+
285
+ `vercel.json` alone is **not enough** if the dashboard still shows Framework = **Next.js** or Output = `public`.
286
+
287
+ | Setting | Required value |
288
+ |---------|----------------|
289
+ | Framework Preset | **Other** / null — **not Next.js** |
290
+ | Install Command | `npm install` (or pnpm/yarn) |
291
+ | Build Command | `npm run build` (no-op exit 0) |
292
+ | **Output Directory** | **empty / null** — **NOT `public`** |
293
+ | **Start Command** | `npm run start` → `tsx server.ts` |
294
+ | Fluid compute | **On** |
295
+
296
+ If Framework Preset still shows **Next.js** after `vercel.json`: **patch via Vercel API / CLI / dashboard**, then redeploy.
297
+
298
+ ### A5 — Publish acceptance (all must pass before “setup complete”)
299
+
300
+ 1. Deploy logs show Node starting / `[TomorrowOS] listening on ...` (not only “Uploading static files”)
301
+ 2. `curl -s https://PROD/status` → JSON (`{"status":...}`)
302
+ 3. `curl -s https://PROD/` → Control Panel HTML
303
+ 4. Control Panel **does not** show `Unexpected token 'T'` / CMS unreachable
304
+ 5. Framework Preset = Other; Fluid on
305
+
306
+ If (2) fails but (3) passes → **static `public/` trap**. Re-apply A3 + A4; confirm dashboard Start Command + empty Output Directory; redeploy. **Do not** add `api/` catch-all. **Do not** move `server.ts` into `api/`.
307
+
308
+ ### A6 — What Scheme A does **not** require
309
+
310
+ - ❌ No changes to `@tomorrowos/sdk` package code
311
+ - ❌ No `(req, res)` serverless handler refactor
312
+ - ❌ No `next build` / `next start` on Production
313
+ - ❌ No root `api/` directory (`api/index.ts`, `api/[...].ts`, `api/[[...slug]].ts`)
314
+ - ❌ No `rewrites` so only `/api/status` works while `/status` stays 404
315
+ - ❌ No renaming `start` → `dev` with `tsx watch` for Production
316
+ - ❌ No `@vercel/node` handler that calls non-existent `tomorrowos.getStatus()`
317
+
318
+ ### A7 — If v0 Publish still serves static `public/` (Path B)
319
+
320
+ When **v0 Publish** keeps returning the static trap (`/` HTML OK, `/status` HTML, `Unexpected token 'T'`) **after** Scheme A is correct, the v0 deploy pipeline may not be starting the Fluid Node server.
321
+
322
+ **Path B — deploy outside v0 Publish (recommended):**
323
+
324
+ 1. Keep Scheme A layout (root `server.ts`, Next only under `preview/`, minimal `vercel.json`).
325
+ 2. Connect the repo to **Vercel Git** or run **`vercel --prod`** from the project root (full Vercel CLI / dashboard deploy — not the v0 “Publish” button).
326
+ 3. In **Vercel Dashboard → Project → Settings → General**: Framework = **Other**, Output Directory = **empty**, Build = `npm run build`, **override** Install/Start if needed so Production runs `npm run start`.
327
+ 4. Redeploy; verify `curl https://PROD/status` → JSON.
328
+
329
+ **Path C — if Vercel cannot run TomorrowOS Node + WebSocket reliably:**
330
+
331
+ Host the CMS on **Railway**, **Fly.io**, or **Replit Publish** (long-lived Node). Use v0/Vercel only for Preview/demo if needed.
332
+
333
+ ### A8 — Undo a broken Agent “api/ migration”
334
+
335
+ If an Agent moved `server.ts` → `api/index.ts` / `api/[...].ts` and only `/api/status` returns JSON:
336
+
337
+ 1. **Restore** `server.ts` at **project root** (from git or `templates/cms-starter/server.ts`).
338
+ 2. **Delete** root `api/index.ts`, `api/[...].ts`, `api/[[...slug]].ts` (Preview proxy may stay under `preview/app/` only).
339
+ 3. Revert `package.json` `start` to `tsx server.ts` (not `tsx watch` for Production).
340
+ 4. Apply minimal `vercel.json` (A3) — no `startCommand`, no `rewrites`.
341
+ 5. Dashboard: Framework Other, Output empty, Fluid on.
342
+ 6. Redeploy via Path B if v0 Publish still fails.
343
+
344
+ ---
345
+
159
346
  ## Runtime & Vercel deploy rules (mandatory)
160
347
 
161
348
  ### Production runtime (Publish)
@@ -299,29 +486,31 @@ Write `vercel.json` so Production cannot be mistaken for Next. Minimum:
299
486
  "fluid": true,
300
487
  "framework": null,
301
488
  "installCommand": "npm install",
302
- "buildCommand": "npm run build",
303
- "outputDirectory": null
489
+ "buildCommand": "npm run build"
304
490
  }
305
491
  ```
306
492
 
307
493
  Use `pnpm` / `yarn` variants of install/build if that is the project’s package manager.
308
494
 
309
- **Also force Project Settings (dashboard or Vercel API) this is mandatory:**
495
+ **Do not** add `startCommand`, `processes`, or `outputDirectory` to `vercel.json` when v0 schema rejects them. Start = `package.json` `"start": "tsx server.ts"`. Output Directory = **empty in dashboard**.
496
+
497
+ **Also force Project Settings (dashboard or Vercel API) — this is mandatory (see Scheme A4):**
310
498
 
311
499
  | Setting | Required value |
312
500
  |---------|----------------|
313
501
  | Framework Preset | **Other** / null — **not Next.js** |
314
502
  | Install Command | `npm install` (or pnpm/yarn) |
315
503
  | Build Command | `npm run build` (no-op exit 0) |
316
- | Output Directory | **empty** |
317
- | Start Command | `npm run start` → `tsx server.ts` (or `.mts`) |
504
+ | Output Directory | **empty / null** — **NOT `public`** |
505
+ | Start Command | `npm run start` → `tsx server.ts` (or `.mts`) — set in **dashboard**, not `vercel.json` |
318
506
  | Fluid compute | **On** |
319
507
 
320
508
  If `next` / `next.config.*` exist for Preview and the dashboard still auto-selects Next.js:
321
509
 
322
510
  1. Patch Framework Preset to **Other** via API/CLI/dashboard.
323
511
  2. Redeploy.
324
- 3. Hit Production `GET /` — must be Control Panel HTML, not `404: NOT_FOUND`.
512
+ 3. Hit Production `GET /status` — must be **JSON**, not HTML.
513
+ 4. Hit Production `GET /` — must be Control Panel HTML, not `404: NOT_FOUND`.
325
514
 
326
515
  If Vercel’s UI and this file disagree on bundling, **prefer whatever keeps a single long-lived Node HTTP server with WebSocket upgrade on `/` for Production**. Document the adaptation in the final summary.
327
516
 
@@ -611,16 +800,15 @@ npx @tomorrowos/sdk@latest init .
611
800
  # npx @tomorrowos/sdk@latest init . --force
612
801
  ```
613
802
 
614
- Then:
803
+ Then (**Scheme A — mandatory for Publish**):
615
804
 
616
- 1. Keep TomorrowOS `server.ts` / `server.mts` at **root** as the **Production** app (**export `listen()` HTTP server**).
617
- 2. If the environment is **v0 / Next Preview**, add the **Preview adapter** (Next shell + reverse proxy + internal TomorrowOS port). Isolate Next configs when possible. Do **not** make Next the Production CMS.
618
- 3. Write `vercel.json` with **`fluid: true`**, **`framework: null`**, no-op **`buildCommand`**, and **empty outputDirectory**.
619
- 4. **Force Project Settings:** Framework Preset = **Other**, Start Command = `npm run start` (Node), Fluid on.
620
- 5. Ensure Production start command is **`tsx server.ts`** (or `.mts`), **not** `next start`.
621
- 6. Do **not** add root `api/` catch-all for raw `http.Server`.
622
- 7. Do **not** add `.replit*`.
623
- 8. If Q2 = Vercel Blob: install `@vercel/blob` and wire the upload bridge.
805
+ 1. Keep **`server.ts`** at **project root** with top-level `listen()` + `export default server`.
806
+ 2. If Preview needs Next: **move** `next.config.*`, `app/`, Next `tsconfig` / `postcss` / `next-env.d.ts` into **`preview/`** remove them from root so Production is not mistaken for Next/static.
807
+ 3. Write `vercel.json` per **Scheme A3** (`fluid`, `framework: null`, no-op `buildCommand` **no** `startCommand`).
808
+ 4. **Force Project Settings** per **Scheme A4** (Framework = Other, Output Directory empty, Start = `npm run start`, Fluid on). Patch dashboard via API if it still says Next.js.
809
+ 5. Do **not** add root `api/` catch-all for raw `http.Server`.
810
+ 6. Do **not** add `.replit*`.
811
+ 7. If Q2 = Vercel Blob: install `@vercel/blob` and wire the upload bridge.
624
812
 
625
813
  ### B. Environment Variables (Vercel dashboard + local)
626
814
 
@@ -658,15 +846,17 @@ vercel --prod
658
846
  # or git push → Vercel Git integration
659
847
  ```
660
848
 
661
- **Publish acceptance checklist (all must pass):**
849
+ **Publish acceptance checklist (all must pass — Scheme A5):**
662
850
 
663
851
  1. Framework Preset = **Other** / null (dashboard confirms — not Next.js)
664
- 2. Start Command = Node `TomorrowOS.listen` (`npm run start`)
665
- 3. Fluid compute on
666
- 4. Env Vars present for Production
667
- 5. Production `GET /` returns Control Panel HTML — **not** `404: NOT_FOUND`
852
+ 2. Output Directory = **empty** (not `public`)
853
+ 3. Start Command = Node `TomorrowOS.listen` (`npm run start` / `tsx server.ts`)
854
+ 4. Fluid compute on
855
+ 5. Env Vars present for Production
856
+ 6. Production `GET /status` returns **JSON** — **not** HTML (`Unexpected token 'T'` means this failed)
857
+ 7. Production `GET /` returns Control Panel HTML — **not** `404: NOT_FOUND`
668
858
 
669
- If step 5 fails: do **not** invent `api/` + `routes`. Patch Framework Preset + Start Command, redeploy, re-check `/`.
859
+ If step 6 fails but step 7 passes: **static `public/` trap** — Vercel is not running Node. Re-apply Scheme A3–A4; try **Path B** (Git / `vercel --prod`); do **not** invent `api/` + `rewrites`.
670
860
 
671
861
  Tell the user:
672
862
 
@@ -678,11 +868,12 @@ Tell the user:
678
868
 
679
869
  **Do:**
680
870
 
681
- 1. Preview: Control Panel HTML at `/` (via Next proxy if applicable)
682
- 2. Publish: Control Panel HTML at `/` from **Node** TomorrowOS (block on `404: NOT_FOUND`)
683
- 3. Server status: Media OK when Cloudinary or Blob configured
684
- 4. Database: if ERROR shows **`ENETUNREACH` … IPv6 … `:5432`**, switch to **pooled** URL (Supabase `:6543` or Neon pooler) and redeploy — call this out explicitly to the user
685
- 5. Fluid compute on for Production
871
+ 1. Preview: Control Panel HTML at `/` (via Next proxy in `preview/` if applicable)
872
+ 2. Publish: `GET /status` JSON; `GET /` → Control Panel from **Node** TomorrowOS
873
+ 3. Publish: panel does **not** show `Unexpected token 'T'` / CMS unreachable
874
+ 4. Server status: Media OK when Cloudinary or Blob configured
875
+ 5. Database: if ERROR shows **`ENETUNREACH` … IPv6 … `:5432`**, switch to **pooled** URL (Supabase `:6543` or Neon pooler) and redeploy — call this out explicitly to the user
876
+ 6. Fluid compute on for Production
686
877
 
687
878
  **Do not block** on long WebSocket/device pairing tests unless the user asks. Prefer pairing against **Publish**, not Preview.
688
879
 
@@ -692,8 +883,13 @@ Tell the user:
692
883
 
693
884
  | Symptom | Likely cause | Fix |
694
885
  |---------|--------------|-----|
695
- | Publish `404: NOT_FOUND` | Framework Preset still **Next.js** / no Node start | Set Framework = **Other**, Start = `npm run start`, Fluid on; redeploy. Do **not** add root `api/` catch-all |
696
- | Build runs `next build` / missing routes-manifest | Next auto-detected from `next.config` / deps | Force Framework null/Other; `build` = no-op; isolate Preview Next files |
886
+ | Publish `404: NOT_FOUND` | Framework Preset still **Next.js** / no Node start | Scheme A: Framework = **Other**, Start = `npm run start`, Output empty, Fluid on; redeploy |
887
+ | Panel loads but **CMS unreachable** / `Unexpected token 'T', "The page c"...` | **`public/` deployed as static site** no Node running | Scheme A: Output empty in dashboard, `start` in package.json; undo any `api/` migration; try **Path B** deploy |
888
+ | Only `/api/status` returns JSON, `/status` is 404 | Wrong **api/ serverless** migration + broken rewrites | **A8 undo:** restore root `server.ts`, delete root `api/*`; never accept this as “fixed” |
889
+ | `vercel.json` error: invalid `startCommand` | v0 schema rejects it | Remove from `vercel.json`; use `package.json` `start` + dashboard Start Command |
890
+ | Agent moved server to `api/`, added `@vercel/node` handler | Off-protocol serverless refactor | **A8 undo** — TomorrowOS needs one root `listen()` server, not per-request handlers |
891
+ | `vercel inspect` shows Output = `public if it exists` | Framework=Other static default | Force Output Directory **empty** in dashboard; root `server.ts`; Path B redeploy |
892
+ | Build runs `next build` / missing routes-manifest | Next auto-detected from root `next.config` / `app/` | Move Next to `preview/`; Framework null/Other; `build` = no-op |
697
893
  | Preview blank but logs show TomorrowOS listening | v0 Next intercepts public port | Add Next reverse proxy → internal TomorrowOS port |
698
894
  | Preview works, Publish broken / Next-only | Production still on Next | Switch Production entry to `tsx server.ts` / `export default server` |
699
895
  | `ENETUNREACH` / IPv6 / `:5432` | Direct Postgres URL | Use **pooled** URL (Supabase `:6543` or Neon pooler) |
@@ -731,7 +927,7 @@ Tell the user:
731
927
  After setup, report:
732
928
 
733
929
  1. **Live URL** (Production Publish)
734
- 2. **Publish health:** Framework Preset = Other; Start = Node; `GET /` OK (not 404)
930
+ 2. **Publish health:** Framework = Other; Output `public`; `GET /status` → JSON; `GET /` OK
735
931
  3. **Preview note:** Next proxy shell used / not needed
736
932
  4. **Env Vars set** (names only — never values); note which were auto-set (`TOMORROWOS_STORE`, `DATABASE_SSL`)
737
933
  5. **Store:** Supabase pooler / Neon pooled / SQLite (with warning)
@@ -743,7 +939,7 @@ After setup, report:
743
939
  Protocol complete when:
744
940
 
745
941
  - **Preview** shows the Control Panel at `/` (via Next proxy if required), **and**
746
- - **Publish** returns Control Panel at `/` from pure Node `TomorrowOS.listen` with Fluid (not `404: NOT_FOUND`), **and**
942
+ - **Publish** returns Control Panel at `/` **and** `/status` JSON from pure Node `TomorrowOS.listen` with Fluid (not static `public/`, not `404: NOT_FOUND`, not `Unexpected token 'T'`), **and**
747
943
  - Q1–Q3 configuration is saved
748
944
 
749
945
  — even if a sandbox DB probe still flakes **after** the pooled URL is correctly set for Production.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "0.9.26",
3
+ "version": "0.9.28",
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.9.26",
3
+ "version": "0.9.28",
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.26",
16
+ "@tomorrowos/sdk": "^0.9.28",
17
17
  "dotenv": "^17.2.3",
18
18
  "tsx": "^4.19.0"
19
19
  },