# Performance Monitoring
## Lighthouse Check (after every deployment)
1. Open Chrome DevTools (F12)
2. Go to Lighthouse tab
3. Select: Performance, Accessibility, Best Practices, SEO
4. Generate Report for both Mobile and Desktop
5. **Target: Score > 90** in all categories
## Common Performance Issues
### Unoptimized Images
```tsx
// Bad - unoptimized, no lazy loading
// Good - explicit dimensions + native lazy loading
```
Pre-resize/compress source images (e.g. with `sharp` in a build step, or an image CDN) — Vite does not do this automatically like Next.js Image did.
### Large JavaScript Bundle
Use dynamic imports for heavy components that aren't needed on initial load:
```tsx
import { lazy, Suspense } from "react";
const HeavyChart = lazy(() => import("./HeavyChart"));
Loading chart...
}>
```
Vite code-splits dynamic imports automatically — check `npm run build`'s output chunk sizes.
### Missing Loading States
Always show feedback during data fetching:
```tsx
// Use shadcn Skeleton component
import { Skeleton } from "@/components/ui/skeleton"
if (isLoading) return
```
### No Caching Strategy
Cache slow backend queries in-process (see [database-optimization.md](database-optimization.md)) rather than re-querying Postgres on every request for rarely-changing data.
## Quick Wins Checklist
- [ ] Images have explicit width/height and `loading="lazy"` where below the fold
- [ ] Heavy components use `React.lazy` + `Suspense`
- [ ] Loading states show skeleton/spinner
- [ ] Fonts loaded via `@font-face`/Google Fonts ``, with `font-display: swap`
- [ ] Production build (`npm run build`) checked for unexpectedly large chunks
## Automated Monitoring
- Self-hosted **Plausible** or **Umami** for privacy-friendly traffic analytics
- `web-vitals` npm package to report Core Web Vitals from real users to your own backend/logging