You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@mieweb/ui is consumed via a committed binary tarball (vendor/mieweb-ui.tgz), not a normal npm dependency or a live submodule build. This document explains why that arrangement exists, why two more direct alternatives (npm registry, direct submodule link) were each tried and blocked, and proposes the automated-rebuild approach as the real fix.
Current State
package.json: "@mieweb/ui": "file:vendor/mieweb-ui.tgz" — a pre-built binary committed to git, manually regenerated by whoever last ran npm run setup:ui.
vendor/ui exists as a real git submodule (tracked in .gitmodules, pointing at https://github.com/mieweb/ui) but nothing rebuilds or consumes it automatically — updating the submodule checkout has zero effect on the app until someone manually reruns setup:ui and commits the new tarball.
.gitignore, vite.config.ts, and scripts/ensure-ui-build.mjs still contain stale comments/dead code from before the tarball migration, claiming the app reads file:vendor/ui directly — it does not.
Net effect: the app can silently run for weeks against a stale, out-of-date UI library build with no automated signal that vendor/ui has moved on.
Why the tarball was introduced (PR #446, commit db9f004d, merged 2026-07-28)
The vendor/ui submodule pointer had drifted onto a commit that only existed on an unpushed local branch (feat/richeditor-collab-yjs) in the mieweb/ui repo. Every CI job that touched the submodule (Frontend, iOS, PR Preview) failed on submodule checkout.
The then-published npm registry version (0.6.1-dev.169) also wasn't a drop-in — its build errored on missing @mieweb/datavis exports that the vendored build resolved.
Fix at the time: vendor a pre-built tarball (npm pack output of vendor/ui) committed directly to the repo, sidestepping both the broken submodule pointer and the incompatible registry release.
Attempt #1: switch straight to the npm registry (blocked, deferred)
PR #475 ("Upgrade @mieweb/ui to 0.7.1 and Prune Unused Editor Dependencies", still open) already tried this exact move — a commit titled chore: install @mieweb/ui from npm instead of a committed tarball — but reverted it within the same PR and explicitly deferred it:
Out of Scope (for Now): Removing the tarball.@mieweb/ui@0.7.1 is now published to the public npm registry, and the original reason for vendoring... no longer holds. Collapsing the tarball + submodule into a plain "@mieweb/ui": "^0.7.1" is a viable follow-up, but it touches CI and belongs in its own PR.
Re-tested independently on a scratch branch in 2026-09: pinning "@mieweb/ui": "0.7.3-dev.29" (npm's next dist-tag, gitHead matching the submodule's current commit exactly) installed cleanly and passed the full gate (typecheck, lint, 138/138 unit tests, build).
Why this is still not the final answer: the exact commit currently on mieweb/ui's main is only published under the next prerelease tag (0.7.3-dev.29), not latest (0.7.3, which is 12 commits behind). We want to depend on the submodule so in-flight fixes there are immediately usable here, without waiting on a registry publish cycle — see next attempt.
Attempt #2: link directly to the submodule (file:vendor/ui) — blocked, root cause found
Switched package.json to "@mieweb/ui": "file:vendor/ui" and rebuilt vendor/ui/dist locally (via pnpm, since vendor/ui declares packageManager: pnpm@10.29.1 and patchedDependencies that plain npm ignores).
Result: npm run typecheck broke across dozens of files. Component prop types collapsed to IntrinsicAttributes & RefAttributes<any> everywhere @mieweb/ui components were used.
Root cause: without npm workspaces, npm install gives vendor/ui (linked via file:) its own separate node_modules tree, including its own physical copy of @types/react — byte-identical to the root app's @types/react, but a structurally distinct type identity to TypeScript. Two separate React.FC/ComponentProps type identities means every prop-typed component from @mieweb/ui type-checks against the wrong React namespace. This is the classic "duplicate module instance" problem, and it's exactly the failure mode the original tarball approach sidestepped (a tarball has no nested node_modules, so there's nothing to duplicate).
Proposed Changes
Keep @mieweb/ui resolved via a tarball (file:vendor/mieweb-ui.tgz) — this is the only approach proven to avoid the duplicate-@types/react problem without adopting npm/pnpm workspaces repo-wide.
Automate the tarball rebuild instead of doing it by hand: detect when vendor/ui's checked-out commit differs from the commit the current tarball was built from, and regenerate (npm run setup:ui) automatically as part of predev/prebuild, so the app always builds against the submodule's current state with zero manual steps.
Clean up the stale artifacts from the original tarball migration: dead scripts/ensure-ui-build.mjs, stale comments in .gitignore and vite.config.ts that still describe the pre-tarball file:vendor/ui arrangement.
Longer-term option (not in this issue): migrate the whole repo to npm/pnpm workspaces so vendor/ui can be a true linked workspace package without the duplicate-instance problem — bigger change, own investigation.
Acceptance Criteria
vendor/ui submodule commit changes are automatically reflected in the app's @mieweb/ui build without a manual npm run setup:ui + commit step
npm run typecheck, npm run lint, npm run test:unit, and npm run build all pass with the automated rebuild in place
Dead code (scripts/ensure-ui-build.mjs) and stale comments referencing file:vendor/ui are removed or corrected
Decision recorded on whether/when to move off the tarball entirely once mieweb/ui's latest npm tag catches up and a workspace-based linking strategy is evaluated
Out of Scope (for Now)
Migrating the whole repo to npm/pnpm workspaces
Removing the tarball entirely in favor of a plain npm registry dependency (blocked on mieweb/ui publishing a stable latest release that matches the commit we need, and on resolving the @kerebron/extension-codecrock@0.8.6 unpatched-crash risk noted in PR Upgrade @mieweb/ui to 0.7.1 and Prune Unused Editor Dependencies #475)
Overview
@mieweb/uiis consumed via a committed binary tarball (vendor/mieweb-ui.tgz), not a normal npm dependency or a live submodule build. This document explains why that arrangement exists, why two more direct alternatives (npm registry, direct submodule link) were each tried and blocked, and proposes the automated-rebuild approach as the real fix.Current State
package.json:"@mieweb/ui": "file:vendor/mieweb-ui.tgz"— a pre-built binary committed to git, manually regenerated by whoever last rannpm run setup:ui.vendor/uiexists as a real git submodule (tracked in.gitmodules, pointing athttps://github.com/mieweb/ui) but nothing rebuilds or consumes it automatically — updating the submodule checkout has zero effect on the app until someone manually rerunssetup:uiand commits the new tarball..gitignore,vite.config.ts, andscripts/ensure-ui-build.mjsstill contain stale comments/dead code from before the tarball migration, claiming the app readsfile:vendor/uidirectly — it does not.vendor/uihas moved on.Why the tarball was introduced (PR #446, commit
db9f004d, merged 2026-07-28)vendor/uisubmodule pointer had drifted onto a commit that only existed on an unpushed local branch (feat/richeditor-collab-yjs) in themieweb/uirepo. Every CI job that touched the submodule (Frontend, iOS, PR Preview) failed on submodule checkout.0.6.1-dev.169) also wasn't a drop-in — its build errored on missing@mieweb/datavisexports that the vendored build resolved.npm packoutput ofvendor/ui) committed directly to the repo, sidestepping both the broken submodule pointer and the incompatible registry release.Attempt #1: switch straight to the npm registry (blocked, deferred)
PR #475 ("Upgrade @mieweb/ui to 0.7.1 and Prune Unused Editor Dependencies", still open) already tried this exact move — a commit titled
chore: install @mieweb/ui from npm instead of a committed tarball— but reverted it within the same PR and explicitly deferred it:Re-tested independently on a scratch branch in 2026-09: pinning
"@mieweb/ui": "0.7.3-dev.29"(npm'snextdist-tag,gitHeadmatching the submodule's current commit exactly) installed cleanly and passed the full gate (typecheck,lint, 138/138 unit tests,build).Why this is still not the final answer: the exact commit currently on
mieweb/ui'smainis only published under thenextprerelease tag (0.7.3-dev.29), notlatest(0.7.3, which is 12 commits behind). We want to depend on the submodule so in-flight fixes there are immediately usable here, without waiting on a registry publish cycle — see next attempt.Attempt #2: link directly to the submodule (
file:vendor/ui) — blocked, root cause foundSwitched
package.jsonto"@mieweb/ui": "file:vendor/ui"and rebuiltvendor/ui/distlocally (viapnpm, sincevendor/uideclarespackageManager: pnpm@10.29.1andpatchedDependenciesthat plainnpmignores).Result:
npm run typecheckbroke across dozens of files. Component prop types collapsed toIntrinsicAttributes & RefAttributes<any>everywhere@mieweb/uicomponents were used.Root cause: without npm workspaces,
npm installgivesvendor/ui(linked viafile:) its own separatenode_modulestree, including its own physical copy of@types/react— byte-identical to the root app's@types/react, but a structurally distinct type identity to TypeScript. Two separateReact.FC/ComponentPropstype identities means every prop-typed component from@mieweb/uitype-checks against the wrongReactnamespace. This is the classic "duplicate module instance" problem, and it's exactly the failure mode the original tarball approach sidestepped (a tarball has no nestednode_modules, so there's nothing to duplicate).Proposed Changes
@mieweb/uiresolved via a tarball (file:vendor/mieweb-ui.tgz) — this is the only approach proven to avoid the duplicate-@types/reactproblem without adopting npm/pnpm workspaces repo-wide.vendor/ui's checked-out commit differs from the commit the current tarball was built from, and regenerate (npm run setup:ui) automatically as part ofpredev/prebuild, so the app always builds against the submodule's current state with zero manual steps.scripts/ensure-ui-build.mjs, stale comments in.gitignoreandvite.config.tsthat still describe the pre-tarballfile:vendor/uiarrangement.vendor/uican be a true linked workspace package without the duplicate-instance problem — bigger change, own investigation.Acceptance Criteria
vendor/uisubmodule commit changes are automatically reflected in the app's@mieweb/uibuild without a manualnpm run setup:ui+ commit stepnpm run typecheck,npm run lint,npm run test:unit, andnpm run buildall pass with the automated rebuild in placescripts/ensure-ui-build.mjs) and stale comments referencingfile:vendor/uiare removed or correctedmieweb/ui'slatestnpm tag catches up and a workspace-based linking strategy is evaluatedOut of Scope (for Now)
mieweb/uipublishing a stablelatestrelease that matches the commit we need, and on resolving the@kerebron/extension-codecrock@0.8.6unpatched-crash risk noted in PR Upgrade @mieweb/ui to 0.7.1 and Prune Unused Editor Dependencies #475)