.claude/skills/audit-lazy-load/SKILL.md
Audit every page to ensure it uses React.lazy() in App.tsx for code-splitting, and that the Suspense fallback delegates to the page's own skeleton. Use after adding pages, before /complete-session, and during performance audits.
npx skillsauth add malhajri07/real-estate-CRM-project audit-lazy-loadInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Every page component must be lazy-loaded via React.lazy() in App.tsx so the initial bundle stays small. The Suspense fallback should be minimal (empty div) because each page handles its own skeleton internally via useMinLoadTime.
App.tsx
└─ const SomePage = lazy(() => import("@/pages/platform/some-page"))
└─ <Suspense fallback={<div className="h-full" />}>
<SomePage />
</Suspense>
SomePage/index.tsx (inside the lazy chunk)
└─ useMinLoadTime() → shows SomePageSkeleton while loading
└─ useQuery() → fetches data
└─ renders skeleton OR real content
This two-layer approach means:
useMinLoadTime)A page is compliant when:
App.tsx via React.lazy(() => import("@/pages/...")) — NOT a static importSuspense boundary (via the withSuspense helper or explicit <Suspense>)useMinLoadTime is called and the skeleton is shown during loadingThese critical public routes are loaded eagerly because they're part of the initial landing experience:
Landing (@/pages/landing)NotFound (@/pages/not-found)SignupSelection, SignupIndividual, SignupCorporate, SignupSuccess, KYCSubmitted (@/pages/signup/*)Sidebar, PlatformShell, Header (layout components, not pages)Everything else — all platform pages, admin pages, client portal pages — must be lazy-loaded.
Read App.tsx and collect:
lazy(() => import(...)) declarations → the "lazy set"import ... from "@/pages/..." declarations → the "eager set"Inventory all page files. Collect every index.tsx or named .tsx under:
apps/web/src/pages/platform/apps/web/src/pages/admin/apps/web/src/pages/client/apps/web/src/pages/marketing/apps/web/src/pages/requests/apps/web/src/pages/map/apps/web/src/pages/listing/apps/web/src/pages/blog.tsxCross-reference. For each page file, check:
Check Suspense wrapping. Every lazy component must be rendered inside <Suspense>. In this project, the withSuspense() helper handles this. Verify each lazy component is either:
withSuspense(Component), orplatformShellRoutes / platformDynamicRoutes / platformAdditionalRoutes array (which the PlatformShell renders inside Suspense)Check page-level skeleton. For each lazy-loaded page, verify it internally uses useMinLoadTime + a skeleton (delegate to /audit-skeleton if needed).
Report a table: | Page file | Import type | Suspense | Page skeleton | Status | |-----------|-------------|----------|---------------|--------| | platform/leads | lazy | withSuspense | LeadsSkeleton | OK | | platform/inbox | static | — | — | NEEDS LAZY | | admin/cms | lazy | withSuspense | — | NEEDS SKELETON |
Fix violations:
lazy(() => import(...)) declarationswithSuspense or is in a Suspense-wrapped route array/audit-skeleton steps)Run /typecheck to confirm zero TS errors.
React.lazy() in App.tsx<Suspense> (via withSuspense or route array)<div className="h-full" /> or <div className="min-h-screen bg-background" />)useMinLoadTime + a layout-accurate skeleton/typecheck passesReact.lazy for layout components (Sidebar, Header, PlatformShell) — these are needed immediatelyloading prop on wouter <Route> — the project uses Suspense + useMinLoadTime insteadtesting
Create and edit Obsidian Flavored Markdown with wikilinks, embeds, callouts, properties, and other Obsidian-specific syntax. Use when working with .md files in Obsidian, or when the user mentions wikilinks, callouts, frontmatter, tags, embeds, or Obsidian notes.
tools
Interact with Obsidian vaults using the Obsidian CLI to read, create, search, and manage notes, tasks, properties, and more. Also supports plugin and theme development with commands to reload plugins, run JavaScript, capture errors, take screenshots, and inspect the DOM. Use when the user asks to interact with their Obsidian vault, manage notes, search vault content, perform vault operations from the command line, or develop and debug Obsidian plugins and themes.
data-ai
Create and edit Obsidian Bases (.base files) with views, filters, formulas, and summaries. Use when working with .base files, creating database-like views of notes, or when the user mentions Bases, table views, card views, filters, or formulas in Obsidian.
tools
Create and edit JSON Canvas files (.canvas) with nodes, edges, groups, and connections. Use when working with .canvas files, creating visual canvases, mind maps, flowcharts, or when the user mentions Canvas files in Obsidian.