ReviewOS

stacks/bench-review

Migration plan: adopt framework-as-dependencies (from vendored workspace)

#73
Closed glennmichael123 opened this 10 days ago ·
10 days ago

Context

Stacks is moving from a vendored framework (storage/framework/ consumed as workspace packages) to consuming it as published @stacksjs/* npm packages (the newer workflow; also enables buddy extension:* browser-extension builds).

Unlike the sibling apps bughq / ghostanalytics - which are already transitional (framework in node_modules, storage/framework/ excluded from tsconfig, near drop-in removal) - bench-review is on the pure original vendored model, so this is a larger, higher-risk migration.

Current state (assessed 2026-07-20)

  • Not currently installed: no node_modules (only bun.lock + pantry/). There is no running baseline to diff a migration against.
  • Framework = vendored workspace: workspaces: ['storage/framework/**', ...], stacks: "workspace:*", and storage/framework/ is ~101M (93 core packages + defaults/).
  • tsconfig inherits the vendored framework: "extends": "./storage/framework/core/tsconfig.json" - the app's entire TS/build setup comes from the vendored tree.
  • No config/crosswind.ts - so no crosswind content-glob repoint (unlike the sibling apps).
  • Direct deps: stacks@workspace:*, @stacksjs/components@^0.2.82, @stacksjs/stx@^0.2.82, @stacksjs/ts-i18n@0.1.8. App version 0.1.0.

Migration surface (bigger than the sibling apps)

  1. package.json - stacks: "workspace:*" → a published version (e.g. ^0.70.77, matching bughq/ghostanalytics); remove the workspaces: ['storage/framework/**', ...] block so the framework is no longer workspace-linked.
  2. tsconfig.json - replace extends: "./storage/framework/core/tsconfig.json" with a self-contained config that resolves @stacksjs/* from node_modules and excludes storage/framework/ (mirror bughq's / ghostanalytics's target tsconfig).
  3. bun install - pull stacks + @stacksjs/* from npm into node_modules (currently none).
  4. Delete storage/framework/ (~101M) after verification. Keep storage/{logs,keys,app,cloud} (runtime data / deploy state).

Plan

  1. Establish a baseline first. bun install on current main, confirm buddy dev runs (+ /stacks-browse QA). Without a working "before", a migration regression is indistinguishable from a pre-existing break. (node_modules is currently absent.)
  2. Branch chore/adopt-framework-deps.
  3. package.json: stacks → published version; remove the storage/framework/** workspaces.
  4. tsconfig.json: swap the vendored extends for a self-contained config (copy the sibling apps').
  5. bun install → confirm node_modules/@stacksjs/* + stacks populate.
  6. mv storage/framework storage/framework.bak (do not delete yet).
  7. Verify end-to-end: buddy dev + /stacks-browse browser QA on the dashboard/UI, buddy build, buddy lint, buddy test.
  8. Green → rm -rf storage/framework.bak; clean up any stray vendored-path references.
  9. Commit + PR.

Risks / watch-outs (higher than the sibling apps)

  • No current baseline (uninstalled) - do step 0 first.
  • Version compatibility: the app (v0.1.0) was built against the vendored framework; the published stacks@0.70.x meta-package may differ. Expect to reconcile API/version drift - this is not a near-drop-in like the sibling apps.
  • tsconfig replacement is load-bearing: the whole TS/build setup is inherited from the vendored tree; the self-contained replacement must be correct or the build breaks.
  • Verify in the running app with /stacks-browse, not isolated renderView (a recent framework sidebar change passed a headless render but was broken live - resolution + no hydration).
  • Sequence: pilot the near-drop-in apps (bughq/ghostanalytics) first; do bench-review last since it's the riskiest.

Rollback

Nothing destructive until step 7 - mv storage/framework.bak storage/framework + git checkout restores everything.

10 days ago

Update: executed + verified — static-SSG apps are the exception to the Phase-1 blocker

Cross-ref the framework-blocker findings on stacksjs/bughq#8 and stacksjs/ghostanalytics#2: the vendored storage/framework/ is live framework source, and 0.70.145 still hardcodes its paths (@stacksjs/server boot scans defaults/{functions,app/Models}; buddy build/serve/dev dispatch into storage/framework/core/actions/src/**). Dropping the tree breaks API boot and the full app build for SSR apps → blocked on an unshipped framework Phase 1 (package-first resolver with vendored fallback).

That blocker does not apply to bench-review, because it is a static-SSG app — its production path is build.ts → @stacksjs/stx buildApp() → dist/ → Netlify, which is fully package-based. I executed the migration and verified it end-to-end against 0.70.145 published packages.

Executed — branch chore/adopt-framework-deps (local, not pushed; a push triggers the Netlify deploy)

  • package.json: stacks: workspace:* → ^0.70.145; add @stacksjs/ts-analytics; remove the storage/framework/** workspaces
  • bunfig.toml: preload the local self-contained resources/plugins/preloader.ts
  • tsconfig.json / tsconfig.app.json: self-contained, resolve @stacksjs/* from node_modules
  • netlify.toml: drop the cd storage/framework/core && bun run build step from the deploy command
  • bootstrap: detect the project via ./buddy, not storage/framework/core
  • app/Routes.ts + Cms/{PostStore,PostUpdate}Action.ts: repoint relative vendored imports → @stacksjs/defaults / @stacksjs/cms
  • remove the ~101M vendored tree; keep only the generated types/ + auto-imports/

Verified green

CheckResult
bun install638 published packages; every @stacksjs/* a real npm install (no workspace symlinks)
bun run build (build.ts / stx buildApp)37/37 pages, 0 failed
./buddy build views (the Netlify command)37/37, 0 failed
./buddy build (bare)37/37, 0 failed — did not hit the actions/src/build/cli.ts ENOENT the SSR path does
served dist browser QA (/about, /judges)renders correctly (Crosswind CSS, nav, filters, components)
buddy lintclean
typecheck:app130 errors, all pre-existing dead-CMS-scaffold ORM-type noise (already documented in tsconfig.app.json); 0 migration-caused

One honest caveat — buddy dev (live SSR/API dev server) does not bind

./buddy dev boots, prints the Frontend/API/Docs ports, then reports "Frontend, API did not bind within 30s" (HTTP 000). No ENOENT in stdout — a silent boot failure, the SSR-side manifestation of the same Phase-1 blocker (dev boots @stacksjs/server + the vendored dev pipeline). It is not a regression: bench-review shipped with no node_modules, so buddy dev couldn't run before either. For a static app the working loop is bun run build + bun preview.ts (verified), and the Netlify deploy path is unaffected. When Phase 1 lands, buddy dev HMR returns for free.

Net

bench-review is migrated and deployable today on framework-as-dependencies — the static-SSG archetype is safe to flip now. The SSR/API siblings (bughq, ghostanalytics, postline) stay blocked on framework Phase 1.

10 days ago

Precision on the framework state + the buddy dev caveat

After verifying against the installed 0.70.145 (the caveat in my update above leaned on the 0.70.73-based bughq/ghostanalytics analysis):

  1. 0.70.145 already ships most of the framework-as-deps resolver — the build path and buddy action dispatch resolve from the packages, and @stacksjs/server's dir scans are now try/catch-tolerant of a missing tree (7 guards). This migration isn't running ahead of the framework.
  2. The buddy dev "didn't bind" caveat has a precise, one-line root cause — not a vague blocker. @stacksjs/actions/dist/dev/views.js resolves views/layouts/partials via firstExistingPath(...), but leaves componentsDir hardcoded to storage/framework/defaults/resources/components. With the tree gone, the stx dev server has no components dir, so the frontend doesn't come up. The build path resolves components from @stacksjs/components via stx.config.ts, which is why bun run build / buddy build are green. A one-line upstream fix (route componentsDir through the same resolver) restores buddy dev.

Net unchanged: bench-review's static build + Netlify deploy are fully green today.

10 days ago

Final status

Migrated + verified; committed on chore/adopt-framework-deps (fd768ed7, local, not pushed). Static build + Netlify deploy path are green. The recipe is now proven on a second app — postline (#14) — so this isn't a one-off.

Only open item: buddy dev HMR frontend, pinned to the one-line componentsDir straggler in @stacksjs/actions dev/views.js (a framework fix, not an app one). Doesn't affect the static production build.

10 days ago

Closing: the migration described here has happened.

  • package.json has no workspaces block — the storage/framework/** workspace linkage is gone
  • stacks is a published version, 0.70.380, not workspace:*
  • tsconfig.json no longer extends the vendored storage/framework/core/tsconfig.json — no extends at all
  • storage/framework/core/ does not exist; the 93 vendored core packages are deleted
  • node_modules/@stacksjs/* is the resolution path (step 0's missing baseline is long since established — the app builds, lints and typechecks from it)

What still sits under storage/framework/ is not the vendored framework: 1.0G of it is stx/ build caches (ssg-cache, bundle-cache), and defaults/ (13M) is the live app/ → storage/framework/defaults/app/ action-resolution fallback that routes/api.ts depends on. Step 4's "delete storage/framework" was written when that directory was the framework; deleting it wholesale now would break action resolution and throw away caches.

If the remaining 1.0G of cache is worth addressing, that is a gitignore/housekeeping question rather than this migration.

Sign in to comment on this issue.