NYC
skills/erichowens/some_claude_skills/reactive-dashboard-performance

reactive-dashboard-performance

SKILL.md

Reactive Dashboard Performance

Expert in building production-grade reactive dashboards that load in <100ms and have comprehensive test coverage.

Core Expertise

Performance Patterns (Linear, Vercel, Notion-grade)

  1. Skeleton-First Loading

    • Render skeleton immediately (0ms perceived load)
    • Stream in data progressively
    • Never show spinners for <200ms loads
  2. Aggressive Caching

    • React Query with staleTime: 5min, cacheTime: 30min
    • Optimistic updates for mutations
    • Prefetch on hover/mount
  3. Code Splitting

    • Route-based splitting (Next.js automatic)
    • Component-level lazy() for heavy widgets
    • Preload critical paths
  4. Memoization Strategy

    • useMemo for expensive computations
    • React.memo for pure components
    • useCallback for stable references

Testing Reactive Dashboards

  1. Mock Strategy

    • Mock at service boundary (React Query, analytics)
    • Never mock UI components (test real DOM)
    • Use MSW for API mocking when possible
  2. Async Handling

    // WRONG - races with React
    render(<Dashboard />);
    const element = screen.getByText('Welcome');
    
    // RIGHT - waits for async resolution
    render(<Dashboard />);
    const element = await screen.findByText('Welcome');
    
  3. Timeout Debugging

    • Timeouts mean: missing mock, wrong query, or component not rendering
    • Use screen.debug() to see actual DOM
    • Check console for unmocked errors
  4. Test Wrapper Pattern

    const TestProviders = ({ children }) => (
      <QueryClientProvider client={testQueryClient}>
        <AuthProvider>
          {children}
        </AuthProvider>
      </QueryClientProvider>
    );
    

Real-World Examples

  • Linear Dashboard: Skeleton → Stale data → Fresh data (perceived <50ms)
  • Vercel Dashboard: Prefetch on nav hover, optimistic deploys
  • Notion Pages: Infinite cache, local-first, sync in background

Diagnostic Protocol

Integration Test Timeouts

  1. Check what's actually rendering

    render(<Component />);
    screen.debug(); // See actual DOM
    
  2. Find unmocked dependencies

    • Check console for "not a function" errors
    • Look for network requests in test output
    • Verify all contexts are provided
  3. Fix async queries

    • Use findBy* instead of getBy*
    • Increase timeout if needed: waitFor(() =&gt; {...}, { timeout: 3000 })
    • Mock React Query properly
  4. Simplify component tree

    • Test widgets individually first
    • Add full integration tests last
    • Use data-testid for complex queries

Performance Optimization

Dashboard Load Budget

Phase Target
Skeleton render 0-16ms (1 frame)
First data paint <100ms
Full interactive <200ms
Lazy widgets <500ms

React Query Config

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 60 * 1000, // 5min
      cacheTime: 30 * 60 * 1000, // 30min
      refetchOnWindowFocus: false,
      refetchOnMount: false,
      retry: 1,
    },
  },
});

Skeleton Pattern

function Dashboard() {
  const { data, isLoading } = useQuery('dashboard', fetchDashboard);

  // Show skeleton immediately, no loading check
  return (
    <div>
      {data ? <RealWidget data={data} /> : <SkeletonWidget />}
    </div>
  );
}

Common Pitfalls

  1. Spinners for fast loads - Use skeletons instead
  2. Unmemoized expensive computations - Wrap in useMemo
  3. Testing implementation details - Test user behavior
  4. Mocking too much - Mock at boundaries only
  5. Synchronous test expectations - Everything is async

When debugging test timeouts, ALWAYS start with screen.debug() to see what actually rendered.

Weekly Installs
29
First Seen
Jan 24, 2026
Installed on
claude-code22
codex21
opencode21
cursor21
gemini-cli19
antigravity19