feat: defer initialization calls until modal is opened. Add loading skeleton
Summary
Defers all AppKit initialization network requests until the modal is actually opened, eliminating HTTP requests on page load. While initialization runs, the modal shows a fast-loading shimmer skeleton so the UI remains responsive. This improves page performance and perceived responsiveness without changing user-facing flows. See compare view for full diff: reown-com/appkit: tomas/apkt-4148-remove-all-http-requests-from-page-load.
Motivation
- Reduce page-load cost and remove unsolicited background calls.
- Improve Core Web Vitals by deferring non-critical work.
- Maintain a smooth UX with immediate visual feedback when users open the modal.
What’s Changed
- Modal initialization is now lazy:
- Defers API/metadata fetches and provider probing until the first modal open.
- Renders a shimmer skeleton instantly while data loads.
- Error utilities consolidated:
- Moved
ErrorUtilfrom@reown/appkit-utilsinto controllers’ utils to be closer to call sites and avoid utils-level coupling.
- Moved
- UI updates:
-
w3mmodal and related views usewui-shimmerplaceholders during initialization. - Connecting and email login views updated to avoid preloading network work.
-
- Adapters:
- Wagmi and Solana adapters no longer trigger eager initialization on page load.
- Tests:
- Updated to reflect lazy init behavior and skeleton rendering.
Notable Files (high level)
- App init and gating:
@reown/appkitclient (packages/appkit/src/client/appkit*.ts) - Controllers:
ApiController,ModalControllerlazy init gates - UI:
packages/scaffold-ui/src/modal/w3m-modaland views usewui-shimmer - Adapters:
wagmi/AuthConnector,solana/clientstop eager work - Utilities:
ErrorUtilmoved topackages/controllers/src/utils/ErrorUtil.tswith export updates
Before vs After
- Before: AppKit performed HTTP requests during page load.
- After: No HTTP requests on page load. First open of the modal triggers initialization; users see a shimmer skeleton while data loads. Subsequent opens are fast due to cached state.
Developer Impact
- Public API: No intended breaking changes.
- Import note (internal): If anything imported
ErrorUtilfrom@reown/appkit-utils, update to use@reown/appkit-controllers/utils.
How to Test
- Verify no network calls on page load:
- Open DevTools Network tab, hard-refresh; expect 0 AppKit HTTP requests before user interaction.
- Open the modal:
- Expect shimmer skeleton to render immediately.
- Data populates as soon as initialization completes.
- Repeat open:
- Modal should open without shimmer (warm state) or very briefly with faster resolution.
- Re-run unit tests:
-
pnpm testshould pass across updated packages.
-
- Sanity-check flows:
- Email/social login views still function; skeleton appears during their initial connect states.
Performance/UX Expectations
- Reduced main-thread and network activity during initial load.
- Better First Input Delay/Interaction to Next Paint by deferring non-critical work.
- Immediate visual feedback via shimmer reduces perceived wait time.
Risks and Mitigations
- Risk: Any logic still relying on eager initialization may fail on first open.
- Mitigation: Controllers gate actions until init completes; tests updated.
- Risk: Adapters that assumed pre-initialized providers.
- Mitigation: Adjusted Wagmi/Solana paths to lazily setup; covered by tests.
Follow-ups
- Consider idle-time prefetch after first user interaction (not page load).
- Instrument timing to measure shimmer duration and init latency across environments.
Related
-
APKT-4148: Remove all HTTP requests from page load
-
Compare diff: GitHub compare view
-
Key changes:
- Deferred initialization across
@reown/appkitclient,ApiController,ModalController. - Shimmer skeleton added to
w3mmodal/views viawui-shimmer. - Eager adapter work removed (Wagmi/Solana).
-
ErrorUtilrelocated to controllers’ utils; exports updated. - Tests updated to reflect lazy init and skeleton rendering.
- Deferred initialization across
Type of change
- [ ] Chore (non-breaking change that addresses non-functional tasks, maintenance, or code quality improvements)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
Associated Issues
Closes APKT-4148
Showcase (Optional)
https://github.com/user-attachments/assets/6efcea72-dbb3-4ddd-87d1-c2f59ac75d55
Checklist
- [ ] Code in this PR is covered by automated tests (Unit tests, E2E tests) => wip
- [x] My changes generate no new warnings
- [x] I have reviewed my own code
- [x] I have filled out all required sections
- [x] I have tested my changes on the preview link
- [ ] Approver of this PR confirms that the changes are tested on the preview link
[!NOTE] Defers initialization/config fetches until the modal opens, shows a shimmer loading state during validation, and relocates ErrorUtil to controllers with corresponding controller/UI/adapter/test updates.
- Core/Controllers:
- Defer project/config/usage/origin validation to
ModalController.open()viaApiController.validateProjectConfig(); addstate.validating/validatedConfigandcheckAllowedOrigins.- Stop eager remote config/origin checks in client; remove AppKit client origin-check path and onramp/SIWX setup from init.
- Update
OptionsControllerstate (addfeatureOverride,basic) and keep remote features/pay gating; exportConfigUtil/ErrorUtilfrom controllers utils.ConfigUtil.fetchRemoteFeatures()now reads fromOptionsController.state(no params) and warns via inline message.- UI:
- Add shimmer loading to
w3m-connect-viewwhileApiController.state.validating; subscribe to validation state.w3m-modal: remove analytics prefetch on load; retain prefetch on open/embedded flow.wui-flex: makepaddinga non-attribute prop to support array values.- Auth/Adapters:
- Create auth provider after remote features on modal open; avoid eager auth setup.
- Update Solana/Wagmi adapters to import
ErrorUtilfrom@reown/appkit-controllers/utils.- Utils/Errors:
- Move
ErrorUtilfrom@reown/appkit-utilsto@reown/appkit-controllers/utils; adjust imports across packages.- Tests:
- Update tests to reflect lazy init, validation-on-open, shimmer loading, and new utils paths.
- Version/Meta:
- Bump
@reown/appkitto1.8.11.- Changeset: patch releases across affected packages.
Written by Cursor Bugbot for commit 7eefa0e1a96369d1d09d11fa835468abaae0d841. This will update automatically on new commits. Configure here.
🦋 Changeset detected
Latest commit: 7eefa0e1a96369d1d09d11fa835468abaae0d841
The changes in this PR will be included in the next version bump.
This PR includes changesets to release 24 packages
| Name | Type |
|---|---|
| @reown/appkit-adapter-solana | Patch |
| @reown/appkit-adapter-wagmi | Patch |
| @reown/appkit-utils | Patch |
| @reown/appkit-controllers | Patch |
| @reown/appkit-scaffold-ui | Patch |
| @reown/appkit | Patch |
| @reown/appkit-ui | Patch |
| @reown/appkit-cdn | Patch |
| @reown/appkit-adapter-bitcoin | Patch |
| @reown/appkit-adapter-ethers | Patch |
| @reown/appkit-adapter-ethers5 | Patch |
| @reown/appkit-siwe | Patch |
| @reown/appkit-siwx | Patch |
| @reown/appkit-wallet-button | Patch |
| @reown/appkit-experimental | Patch |
| @reown/appkit-pay | Patch |
| @reown/appkit-core | Patch |
| @reown/appkit-universal-connector | Patch |
| @reown/appkit-testing | Patch |
| @reown/appkit-common | Patch |
| @reown/appkit-polyfills | Patch |
| @reown/appkit-wallet | Patch |
| @reown/appkit-cli | Patch |
| @reown/appkit-codemod | Patch |
Not sure what this means? Click here to learn what changesets are.
Click here if you're a maintainer who wants to add another changeset to this PR
The latest updates on your projects. Learn more about Vercel for GitHub.
| Project | Deployment | Preview | Comments | Updated (UTC) |
|---|---|---|---|---|
| appkit-basic-html | Preview | Comment | Oct 29, 2025 0:43am | |
| appkit-demo | Oct 29, 2025 0:43am | |||
| appkit-gallery | Comment | Oct 29, 2025 0:43am | ||
| appkit-laboratory | Oct 29, 2025 0:43am |
10 Skipped Deployments
| Project | Deployment | Preview | Comments | Updated (UTC) |
|---|---|---|---|---|
| appkit-basic-example | Oct 29, 2025 0:43am | |||
| appkit-basic-sign-client-example | Oct 29, 2025 0:43am | |||
| appkit-basic-up-example | Oct 29, 2025 0:43am | |||
| appkit-ethers5-bera | Oct 29, 2025 0:43am | |||
| appkit-nansen-demo | Oct 29, 2025 0:43am | |||
| appkit-vue-solana | Oct 29, 2025 0:43am | |||
| appkit-wagmi-cdn-example | Oct 29, 2025 0:43am | |||
| ethereum-provider-wagmi-example | Oct 29, 2025 0:43am | |||
| next-wagmi-solana-bitcoin-example | Oct 29, 2025 0:43am | |||
| vue-wagmi-example | Oct 29, 2025 0:43am |
Visual Regression Test Results ✅ Passed
✨ No visual changes detected
Chromatic Build: https://www.chromatic.com/build?appId=6493191bf4b10fed8ca7353f&number=253 Storybook Preview: https://6493191bf4b10fed8ca7353f-gfvraznaun.chromatic.com/
📦 Bundle Size Check
❌ Some bundles exceed size limits
📊 View detailed bundle sizes
> @reown/[email protected] size /home/runner/work/appkit/appkit
> size-limit
@reown/appkit - Main Entry
Size limit: 80 kB
Size: 75.17 kB with all dependencies, minified and gzipped
Loading time: 1.5 s on slow 3G
Running time: 482 ms on Snapdragon 410
Total time: 2 s
@reown/appkit/react
Package size limit has exceeded by 915 B
Size limit: 230 kB
Size: 230.91 kB with all dependencies, minified and gzipped
Loading time: 4.6 s on slow 3G
Running time: 1.2 s on Snapdragon 410
Total time: 5.7 s
@reown/appkit/vue
Size limit: 80 kB
Size: 75.17 kB with all dependencies, minified and gzipped
Loading time: 1.5 s on slow 3G
Running time: 734 ms on Snapdragon 410
Total time: 2.3 s
@reown/appkit-scaffold-ui
Size limit: 220 kB
Size: 217.14 kB with all dependencies, minified and gzipped
Loading time: 4.3 s on slow 3G
Running time: 564 ms on Snapdragon 410
Total time: 4.9 s
@reown/appkit-ui
Size limit: 500 kB
Size: 13.15 kB with all dependencies, minified and gzipped
Loading time: 257 ms on slow 3G
Running time: 62 ms on Snapdragon 410
Total time: 319 ms
Try to reduce size or increase limit at .size-limit.js
ELIFECYCLE Command failed with exit code 1.
Coverage Report
| Status | Category | Percentage | Covered / Total |
|---|---|---|---|
| 🔵 | Lines | 80.37% | 36519 / 45435 |
| 🔵 | Statements | 80.37% | 36519 / 45435 |
| 🔵 | Functions | 78.68% | 3957 / 5029 |
| 🔵 | Branches | 86.37% | 8822 / 10214 |
File Coverage
| Warnings | |
|---|---|
| :warning: |
🌐 Non-company domain introduced (host: example.com) in packages/controllers/tests/controllers/ApiController.test.ts (line 150): |
Generated by :no_entry_sign: dangerJS against 7eefa0e1a96369d1d09d11fa835468abaae0d841
Opening the modal looks a bit flashy now (you see the loaders and then immediately you see the wallet options). Could we animate out the loaders and animate in the wallet content, so this is more visually pleasing.
@tomiir I assume the initializing part is faster now?