This PR tackles the performance caused by the App Store / circular dependencies. /claim #23104
The Diagnosis:
Using madge to analyze the dependency graph, I identified a critical circular dependency chain (75+ cycles) where the generic InstallAppButton was statically importing the entire App Store catalog (apps.browser.generated.tsx).
The chain looked like this:
InstallAppButton -> InstallAppButtonWithoutPlanCheck -> InstallAppButtonMap (The whole store) -> Alby (and others) -> AppCard -> OmniInstallAppButton -> InstallAppButton.
The Fix:
I refactored InstallAppButtonWithoutPlanCheck.tsx to switch from a synchronous static import to an asynchronous dynamic import using useEffect.
InstallAppButtonMap is now lazy-loaded only when the component mounts, preventing the entire App Store from being bundled into the initial page load of the Dashboard/Settings.Note: Due to hardware limitations (my machine cannot handle the 16GB RAM requirement for the Node process in this monorepo) and issues verifying via Codespaces, I was unable to run the full dev server or the test suite locally.
I coded this fix based on static analysis data and assistance from LLMs (Gemini) to ensure the React Hooks logic (useState, useEffect) handles the async loading safely (including isMounted checks). I am requesting the maintainers or reviewers to please verify the runtime behavior and test suite on my behalf.
Before the fix (Analysis Log):
Running npx madge --circular --extensions ts,tsx packages/app-store resulted in 75 circular dependencies. The root cause was the generic install button pulling in every app:
75) InstallAppButton.tsx > InstallAppButtonWithoutPlanCheck.tsx > apps.browser.generated.tsx > alby/components/EventTypeAppCardInterface.tsx > _components/AppCard.tsx > _components/OmniInstallAppButton.tsx
After the fix:
The specific cycle involving InstallAppButton and apps.browser.generated.tsx is broken. The madge count should drop significantly (ideally to 1 or 0 runtime cycles), and the initial JS bundle size for the Dashboard should be drastically reduced.
Since I could not run the environment locally, please test the following steps:
npx madge --circular --extensions ts,tsx packages/app-store. Confirm that the circular dependency count has dropped and the InstallAppButton loop is gone.InstallAppButton.
.next/server/chunks folder or the network tab. The initial bundle size should be smaller.yarn workspace @calcom/app-store test.
getByRole might need to be updated to await findByRole to handle the useEffect timing.Alexandros Pappas
@apappas1129
Cal.com, Inc.
@cal