Skip to content

fix(pro): regenerate /pro bundle so deployed assets reflect #3227 Clerk fix#3228

Merged
koala73 merged 1 commit into
mainfrom
fix/rebuild-pro-bundle-no-rhc
Apr 20, 2026
Merged

fix(pro): regenerate /pro bundle so deployed assets reflect #3227 Clerk fix#3228
koala73 merged 1 commit into
mainfrom
fix/rebuild-pro-bundle-no-rhc

Conversation

@koala73

@koala73 koala73 commented Apr 20, 2026

Copy link
Copy Markdown
Owner

Why this PR exists

PR #3227 fixed `pro-test/src/services/checkout.ts` to import `@clerk/clerk-js/no-rhc` instead of the headless main export. It merged at 09:45 UTC and deployed, but production /pro still throws "Clerk was not loaded with Ui components" because:

  • `public/pro/` is committed to the repo, not built by Vercel.
  • The root `vite build` only builds the main app — it does NOT run `pro-test/`'s build.
  • fix(pro): switch Clerk to no-rhc bundle so sign-in modal mounts on /pro #3227 changed the source but never ran `cd pro-test && npm run build`, so `public/pro/assets/clerk-C6kUTNKl.js` (the old, broken Clerk headless chunk) shipped unchanged.

This PR rebuilds pro-test against the post-#3227 source and commits the regenerated bundle.

Diff

```

  • public/pro/assets/clerk-C6kUTNKl.js (DEL — old Clerk headless build)
  • public/pro/assets/index-J1JYVlDk.js (DEL — old app bundle pointing at it)
  • public/pro/assets/clerk.no-rhc-UeQvd9Xf.js (NEW — bundled-UI Clerk, 810KB)
  • public/pro/assets/index-CFLOgmG-.js (NEW — app bundle pointing at it)
    M public/pro/index.html (script src updated to new chunk hashes)
    ```

No source changes — just the build output that #3227 should have included.

Test plan

Follow-up: prevent recurrence

A separate PR will add (a) a pre-push hook that detects `pro-test/src/**` changes and refuses to push if `public/pro/` is out of date, and (b) a CI check that runs `cd pro-test && npm run build` and fails if the working tree has uncommitted diffs in `public/pro/`. Without these, this footgun will fire again every time someone touches the pricing page or checkout flow.

…3227

PR #3227 fixed pro-test/src/services/checkout.ts to import
@clerk/clerk-js/no-rhc instead of the headless main export, but the
deployed bundle in public/pro/assets/ was never regenerated. The
Vercel deploy ships whatever is committed under public/pro/ — the
root build script does not run pro-test's vite build — so
production /pro continued serving the old broken clerk-C6kUTNKl.js
even after #3227 merged. Sign-in still threw "Clerk was not loaded
with Ui components".

Rebuild: cd pro-test && npm run build, which writes the new chunks
to ../public/pro/assets/. Deletes the stale clerk-C6kUTNKl.js +
index-J1JYVlDk.js, adds clerk.no-rhc-UeQvd9Xf.js +
index-CFLOgmG-.js, and updates pro/index.html to reference them.
@vercel

vercel Bot commented Apr 20, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
worldmonitor Ignored Ignored Apr 20, 2026 10:01am

Request Review

@greptile-apps

greptile-apps Bot commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR commits the regenerated public/pro/ build output that was missing from PR #3227. The source fix (@clerk/clerk-js/no-rhc import) shipped in #3227, but the committed static bundle was never rebuilt, so production continued serving the broken headless Clerk chunk. This PR deletes the two stale assets and replaces them with the correctly built artifacts: clerk.no-rhc-UeQvd9Xf.js (full UI Clerk, ~810 KB) and index-CFLOgmG-.js, with index.html updated to reference the new entry hash.

Confidence Score: 5/5

Safe to merge — build artifacts are internally consistent and directly address the production Clerk modal failure.

All four changed files are Vite build outputs. The new index bundle verifiably references clerk.no-rhc-UeQvd9Xf.js, the HTML entry point is updated to the new hash, and the stale headless chunks are deleted. No source logic changes are present and no P0/P1 issues were identified.

No files require special attention.

Important Files Changed

Filename Overview
public/pro/index.html Single-line change updates script src hash from index-J1JYVlDk.js to index-CFLOgmG-.js; all other metadata, CSP-adjacent attributes, and hreflang tags are untouched.
public/pro/assets/clerk.no-rhc-UeQvd9Xf.js New Clerk chunk built from @clerk/clerk-js/no-rhc (UI-capable, ~810 KB); replaces the old headless-only clerk-C6kUTNKl.js that caused 'Clerk was not loaded with UI components' errors.
public/pro/assets/index-CFLOgmG-.js New app entry bundle; grep confirms it references clerk.no-rhc-UeQvd9Xf.js, consistent with the #3227 source change. Old index-J1JYVlDk.js deleted.
public/pro/assets/clerk-C6kUTNKl.js Deleted — was the stale headless Clerk bundle that caused the production modal failure.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["index.html\n(entry point)"] -->|"script src\nindex-CFLOgmG-.js"| B["index-CFLOgmG-.js\n(app bundle)"]
    B -->|"dynamic import\nclerk.no-rhc-UeQvd9Xf.js"| C["clerk.no-rhc-UeQvd9Xf.js\n(Clerk UI bundle, ~810 KB)"]
    C --> D["✅ Sign-in modal\nmounts correctly"]

    E["index.html (old)"] -->|"script src\nindex-J1JYVlDk.js"| F["index-J1JYVlDk.js\n(old app bundle)"]
    F -->|"dynamic import\nclerk-C6kUTNKl.js"| G["clerk-C6kUTNKl.js\n(headless Clerk, no UI)"]
    G --> H["❌ 'Clerk was not loaded\nwith UI components'"]

    style D fill:#22c55e,color:#fff
    style H fill:#ef4444,color:#fff
    style C fill:#3b82f6,color:#fff
    style G fill:#f97316,color:#fff
Loading

Reviews (1): Last reviewed commit: "fix(pro): regenerate /pro bundle with no..." | Re-trigger Greptile

koala73 added a commit that referenced this pull request Apr 20, 2026
…taleness

public/pro/ is committed to the repo and served verbatim by Vercel.
The root build script only runs the main app's vite build — it does
NOT run pro-test's build. So any PR that changes pro-test/src/**
without manually running `cd pro-test && npm run build` and committing
the regenerated chunks ships to production with a stale bundle.

This footgun just cost us: PR #3227 fixed the Clerk "not loaded with
Ui components" sign-in bug in source, merged, deployed — and the live
site still threw the error because the committed chunk under
public/pro/assets/ was the pre-fix build. PR #3228 fix-forwarded by
rebuilding.

Two-layer enforcement so it doesn't happen again:

1. .husky/pre-push — mirrors the existing proto freshness block.
   If pro-test/ changed vs origin/main, rebuild and `git diff
   --exit-code public/pro/`. Blocks the push with a clear message if
   the bundle is stale or untracked files appear.

2. .github/workflows/pro-bundle-freshness.yml — CI backstop on any
   PR touching pro-test/** or public/pro/**. Runs `npm ci + npm run
   build` in pro-test and fails the check if the working tree shows
   any diff or untracked files under public/pro/. Required before
   merge, so bypassing the local hook still can't land a stale
   bundle.

Note: the hook's diff-against-origin/main check means it skips the
build when pushing a branch that already matches main on pro-test/
(e.g. fix-forward branches that only touch public/pro/). CI covers
that case via its public/pro/** path filter.
@koala73
koala73 merged commit 2b7f83f into main Apr 20, 2026
11 checks passed
@koala73
koala73 deleted the fix/rebuild-pro-bundle-no-rhc branch April 20, 2026 10:24
koala73 added a commit that referenced this pull request Apr 20, 2026
The first scoping fix used `^pro-test/` only, but the CI workflow
keys off both `pro-test/**` AND `public/pro/**`. That left a gap: a
bundle-only PR (e.g. a fix-forward rebuild like #3228, or a hand-edit
to a committed asset) skipped the local check entirely while CI would
still validate it. The hook and CI are now consistent.

Trigger condition: `^(pro-test|public/pro)/` — the rebuild + diff
check now fires whenever the branch delta touches either side of the
source/artifact pair, matching the CI workflow's path filter.
koala73 added a commit that referenced this pull request Apr 20, 2026
The actual root cause behind the "Clerk was not loaded with Ui
components" sign-in failure on /pro is NOT the import path — it's
that pro-test was on @clerk/clerk-js v6.4.0 while the main app
(which works fine) is on v5.125.7.

Clerk v6 fundamentally changed `clerk.load()`: the UI controller
is no longer auto-mounted by default. Both `@clerk/clerk-js` (the
default v6 entry) and `@clerk/clerk-js/no-rhc` (the bundled-UI
variant) expect the caller to either:
  - load Clerk's UI bundle from CDN and pass `window.__internal_ClerkUICtor`
    to `clerk.load({ ui: { ClerkUI } })`, or
  - manually wire up `clerkUICtor`.

That's why my earlier "switch to no-rhc" fix (PR #3227 + #3228)
didn't actually unbreak production — both v6 variants throw the same
assertion. The error stack on the deployed bundle confirmed it:
`assertComponentsReady` from `clerk.no-rhc-UeQvd9Xf.js`.

Fix: pin pro-test to `@clerk/clerk-js@^5.125.7` to match the main
app's working version. v5 still auto-mounts UI on `clerk.load()` —
no extra wiring needed. The plain `import { Clerk } from '@clerk/clerk-js'`
pattern (which the main app uses verbatim and which pro-test had
before #3227) just works under v5.

Verification of the rebuilt bundle (chunk: clerk-PNSFEZs8.js):
  - 3.05 MB (matches main app's clerk-DC7Q2aDh.js: 3.05 MB)
  - 44 occurrences of mountComponent (matches main: 44)
  - 3 occurrences of SignInComponent (matches main: 3)
  - 0 occurrences of "Clerk was not loaded with Ui" (the assertion
    error string is absent; UI is unconditionally mounted)

Includes the rebuilt public/pro/ artifacts so this fix is actually
deployed (PR #3229's CI check will catch any future PR that touches
pro-test/src without rebuilding).
koala73 added a commit that referenced this pull request Apr 20, 2026
…op (#3229)

* chore(ci): enforce pro-test bundle freshness, prevent silent deploy staleness

public/pro/ is committed to the repo and served verbatim by Vercel.
The root build script only runs the main app's vite build — it does
NOT run pro-test's build. So any PR that changes pro-test/src/**
without manually running `cd pro-test && npm run build` and committing
the regenerated chunks ships to production with a stale bundle.

This footgun just cost us: PR #3227 fixed the Clerk "not loaded with
Ui components" sign-in bug in source, merged, deployed — and the live
site still threw the error because the committed chunk under
public/pro/assets/ was the pre-fix build. PR #3228 fix-forwarded by
rebuilding.

Two-layer enforcement so it doesn't happen again:

1. .husky/pre-push — mirrors the existing proto freshness block.
   If pro-test/ changed vs origin/main, rebuild and `git diff
   --exit-code public/pro/`. Blocks the push with a clear message if
   the bundle is stale or untracked files appear.

2. .github/workflows/pro-bundle-freshness.yml — CI backstop on any
   PR touching pro-test/** or public/pro/**. Runs `npm ci + npm run
   build` in pro-test and fails the check if the working tree shows
   any diff or untracked files under public/pro/. Required before
   merge, so bypassing the local hook still can't land a stale
   bundle.

Note: the hook's diff-against-origin/main check means it skips the
build when pushing a branch that already matches main on pro-test/
(e.g. fix-forward branches that only touch public/pro/). CI covers
that case via its public/pro/** path filter.

* fix(hooks): scope pro-test freshness check to branch delta, not worktree

The first version of this hook used `git diff --name-only origin/main
-- pro-test/`, which compares the WORKING TREE to origin/main. That
fires on unstaged local pro-test/ scratch edits and blocks pushing
unrelated branches purely because of dirty checkout state.

Switch to `$CHANGED_FILES` (computed earlier at line 77 from
`git diff origin/main...HEAD`), which scopes the check to commits on
the branch being pushed. This matches the convention the test-runner
gates already use (lines 93-97). Also honor `$RUN_ALL` as the safety
fallback when the branch delta can't be computed.

* fix(hooks): trigger pro freshness check on public/pro/ too, match CI

The first scoping fix used `^pro-test/` only, but the CI workflow
keys off both `pro-test/**` AND `public/pro/**`. That left a gap: a
bundle-only PR (e.g. a fix-forward rebuild like #3228, or a hand-edit
to a committed asset) skipped the local check entirely while CI would
still validate it. The hook and CI are now consistent.

Trigger condition: `^(pro-test|public/pro)/` — the rebuild + diff
check now fires whenever the branch delta touches either side of the
source/artifact pair, matching the CI workflow's path filter.
koala73 added a commit that referenced this pull request Apr 20, 2026
…3232)

The actual root cause behind the "Clerk was not loaded with Ui
components" sign-in failure on /pro is NOT the import path — it's
that pro-test was on @clerk/clerk-js v6.4.0 while the main app
(which works fine) is on v5.125.7.

Clerk v6 fundamentally changed `clerk.load()`: the UI controller
is no longer auto-mounted by default. Both `@clerk/clerk-js` (the
default v6 entry) and `@clerk/clerk-js/no-rhc` (the bundled-UI
variant) expect the caller to either:
  - load Clerk's UI bundle from CDN and pass `window.__internal_ClerkUICtor`
    to `clerk.load({ ui: { ClerkUI } })`, or
  - manually wire up `clerkUICtor`.

That's why my earlier "switch to no-rhc" fix (PR #3227 + #3228)
didn't actually unbreak production — both v6 variants throw the same
assertion. The error stack on the deployed bundle confirmed it:
`assertComponentsReady` from `clerk.no-rhc-UeQvd9Xf.js`.

Fix: pin pro-test to `@clerk/clerk-js@^5.125.7` to match the main
app's working version. v5 still auto-mounts UI on `clerk.load()` —
no extra wiring needed. The plain `import { Clerk } from '@clerk/clerk-js'`
pattern (which the main app uses verbatim and which pro-test had
before #3227) just works under v5.

Verification of the rebuilt bundle (chunk: clerk-PNSFEZs8.js):
  - 3.05 MB (matches main app's clerk-DC7Q2aDh.js: 3.05 MB)
  - 44 occurrences of mountComponent (matches main: 44)
  - 3 occurrences of SignInComponent (matches main: 3)
  - 0 occurrences of "Clerk was not loaded with Ui" (the assertion
    error string is absent; UI is unconditionally mounted)

Includes the rebuilt public/pro/ artifacts so this fix is actually
deployed (PR #3229's CI check will catch any future PR that touches
pro-test/src without rebuilding).
koala73 added a commit that referenced this pull request Apr 20, 2026
Reviewer flagged that the first iteration's `window.top !== window`
check was too broad. The repo explicitly markets "Embeddable iframe
panels" as an Enterprise feature
(pro-test/src/locales/en.json: whiteLabelDesc), so legitimate
customer embeds must keep firing premium RPCs normally. Only the /pro
marketing preview — which is known-anonymous and generates expected
401 noise — should short-circuit.

Fix: replace the blanket iframe check with a unique marker that only
/pro's preview iframe carries.

  - pro-test/src/App.tsx: iframe src switched from
    `?alert=false` (dead param, unused in main app) to
    `?embed=pro-preview`. Rebuilt public/pro/ to ship the change.

  - src/utils/embedded-preview.ts: two-gate check now. Gate 1 still
    requires `window.top !== window` so the marker leaking into a
    top-level URL doesn't disable premium RPCs for the top-level app.
    Gate 2 requires `?embed=pro-preview` in location.search so only
    the known embedder matches. Enterprise white-label embeds without
    this marker behave exactly like a top-level visit.

Same three premium fetchers + the one country-intel path still gate
on IS_EMBEDDED_PREVIEW; the semantic change is purely in how the
flag is computed.

Per PR #3229 / #3228 lesson, the pro-test rebuild ships in the same
PR as the source change — public/pro/assets/index-*.js and index.html
reflect the new iframe src.
koala73 added a commit that referenced this pull request Apr 20, 2026
…review iframe (#3235)

* fix(preview): skip premium RPCs when main app runs inside /pro preview iframe

pro-test/src/App.tsx embeds the full main app as a "live preview"
via <iframe src="https://worldmonitor.app?alert=false" sandbox="...">.
The iframe boots an anonymous main-app session, which fires premium
RPCs (get-regional-snapshot, get-tariff-trends, list-comtrade-flows,
and on country-click the fetchProSections batch) with no Clerk bearer
available. Every call 401s, the circuit breakers catch and fall
through to empty fallbacks (so the preview renders fine), but the
401s surface on the PARENT /pro page's DevTools console and Sentry
because `sandbox` includes `allow-same-origin`.

Net effect: /pro pricing page shows a flood of fake-looking errors
that cost us a session of debugging to trace back to the iframe.
PR #3233's premiumFetch swap didn't help here (there's simply no
token to inject for an anonymous iframe).

Introduce `src/utils/embedded-preview.ts::IS_EMBEDDED_PREVIEW`, a
module-level boolean evaluated once at load from
`window.top !== window` (with try/catch for cross-origin sandboxes),
and short-circuit three init-time premium entry points when true:

  - RegionalIntelligenceBoard.loadCurrent → renderEmpty()
  - fetchTariffTrends → return emptyTariffs
  - fetchComtradeFlows → return emptyComtrade

Plus one defensive gate in country-intel.fetchProSections for the
case a user clicks a country inside the iframe preview.

Each gate returns the exact same empty fallback the breaker would
have produced after a 401, so visual behavior is unchanged — the
preview iframe still shows the dashboard layout with empty premium
panels, just without the network request and its console/Sentry
trail.

Live-tab /pro page should now see zero 401s from regional-snapshot /
tariff-trends / comtrade-flows on load.

* fix(preview): narrow iframe gate to ?embed=pro-preview marker only

Reviewer flagged that the first iteration's `window.top !== window`
check was too broad. The repo explicitly markets "Embeddable iframe
panels" as an Enterprise feature
(pro-test/src/locales/en.json: whiteLabelDesc), so legitimate
customer embeds must keep firing premium RPCs normally. Only the /pro
marketing preview — which is known-anonymous and generates expected
401 noise — should short-circuit.

Fix: replace the blanket iframe check with a unique marker that only
/pro's preview iframe carries.

  - pro-test/src/App.tsx: iframe src switched from
    `?alert=false` (dead param, unused in main app) to
    `?embed=pro-preview`. Rebuilt public/pro/ to ship the change.

  - src/utils/embedded-preview.ts: two-gate check now. Gate 1 still
    requires `window.top !== window` so the marker leaking into a
    top-level URL doesn't disable premium RPCs for the top-level app.
    Gate 2 requires `?embed=pro-preview` in location.search so only
    the known embedder matches. Enterprise white-label embeds without
    this marker behave exactly like a top-level visit.

Same three premium fetchers + the one country-intel path still gate
on IS_EMBEDDED_PREVIEW; the semantic change is purely in how the
flag is computed.

Per PR #3229 / #3228 lesson, the pro-test rebuild ships in the same
PR as the source change — public/pro/assets/index-*.js and index.html
reflect the new iframe src.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant