# Web Vitals Monitoring

Tracks Core Web Vitals (LCP, FID, CLS) and sends metrics to Sentry for performance monitoring.

## Features

- **Core Web Vitals Tracking**: LCP, FID, CLS
- **Additional Metrics**: TTFB, FCP, INP
- **Sentry Integration**: Automatic reporting to Sentry Performance Monitoring
- **Google Analytics Support**: Send metrics to GA4
- **Performance Classification**: Automatic good/needs-improvement/poor ratings
- **Poor Performance Alerts**: Capture Sentry warnings for poor metrics

## Quick Start

### 1. Install Dependencies

```bash
npm install web-vitals @sentry/nextjs
```

### 2. Set Up Sentry

Configure your `NEXT_PUBLIC_SENTRY_DSN` in `.env.local`:

```env
NEXT_PUBLIC_SENTRY_DSN=your-sentry-dsn
```

### 3. Initialize in Your App

Add to your root layout (`app/layout.tsx`):

```tsx
'use client';

import { useEffect } from 'react';
import { reportWebVitals } from '@/lib/monitoring/web-vitals';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    // Initialize Web Vitals tracking
    reportWebVitals();
  }, []);

  return (
    <html>
      <body>{children}</body>
    </html>
  );
}
```

Or in a dedicated client component:

```tsx
// app/components/WebVitalsReporter.tsx
'use client';

import { useEffect } from 'react';
import { reportWebVitals } from '@/lib/monitoring/web-vitals';

export function WebVitalsReporter() {
  useEffect(() => {
    reportWebVitals();
  }, []);

  return null;
}
```

Then include it in your layout:

```tsx
// app/layout.tsx
import { WebVitalsReporter } from './components/WebVitalsReporter';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <WebVitalsReporter />
        {children}
      </body>
    </html>
  );
}
```

## Metrics Tracked

### Core Web Vitals

| Metric | Description | Good | Needs Improvement | Poor |
|--------|-------------|------|-------------------|------|
| **LCP** | Largest Contentful Paint | ≤ 2.5s | ≤ 4.0s | > 4.0s |
| **FID** | First Input Delay | ≤ 100ms | ≤ 300ms | > 300ms |
| **CLS** | Cumulative Layout Shift | ≤ 0.1 | ≤ 0.25 | > 0.25 |

### Additional Metrics

| Metric | Description | Good | Needs Improvement | Poor |
|--------|-------------|------|-------------------|------|
| **TTFB** | Time to First Byte | ≤ 800ms | ≤ 1800ms | > 1800ms |
| **FCP** | First Contentful Paint | ≤ 1.8s | ≤ 3.0s | > 3.0s |
| **INP** | Interaction to Next Paint | ≤ 200ms | ≤ 500ms | > 500ms |

## Sentry Integration

Metrics are automatically sent to Sentry with:

1. **Measurements**: Each metric is recorded as a Sentry measurement
2. **Breadcrumbs**: Metric events are logged as breadcrumbs for context
3. **Performance Warnings**: Poor metrics trigger Sentry warnings with full context

### Viewing in Sentry

1. Go to **Performance** → **Web Vitals**
2. View aggregate metrics across all users
3. Filter by page, browser, or user segments
4. Set up alerts for poor performance

## Google Analytics Integration

If Google Analytics 4 is available (`gtag` function), metrics are automatically sent:

```javascript
gtag('event', metric_name, {
  value: metric_value,
  event_category: 'Web Vitals',
  event_label: metric_id,
  non_interaction: true,
});
```

## Advanced Usage

### Get Current Metrics

```tsx
import { getCurrentMetrics } from '@/lib/monitoring/web-vitals';

async function analyzePerformance() {
  const metrics = await getCurrentMetrics();
  console.log('Current Web Vitals:', metrics);
}
```

### Use Metric Thresholds

```tsx
import { METRIC_THRESHOLDS } from '@/lib/monitoring/web-vitals';

// Check if a value is "good"
if (lcpValue <= METRIC_THRESHOLDS.LCP.good) {
  console.log('LCP is good!');
}
```

### Display Metrics in UI

```tsx
'use client';

import { useEffect, useState } from 'react';
import { getCurrentMetrics } from '@/lib/monitoring/web-vitals';
import type { Metric } from 'web-vitals';

export function PerformanceDebugger() {
  const [metrics, setMetrics] = useState<Metric[]>([]);

  useEffect(() => {
    getCurrentMetrics().then(setMetrics);
  }, []);

  return (
    <div>
      <h2>Performance Metrics</h2>
      {metrics.map((metric) => (
        <div key={metric.name}>
          {metric.name}: {metric.value.toFixed(2)}
        </div>
      ))}
    </div>
  );
}
```

## Testing

Run the test suite:

```bash
npm test -- __tests__/lib/monitoring/web-vitals.test.ts
```

The tests cover:
- Initialization of all metric listeners
- Metric tracking and Sentry integration
- Performance rating (good/needs-improvement/poor)
- Google Analytics integration
- Error handling when Sentry is unavailable
- Server-side rendering (SSR) safety

## Development Mode

In development, metrics are logged to the console:

```
[Web Vitals] {
  name: 'LCP',
  value: 1234.56,
  rating: 'good',
  id: 'v3-1234567890'
}
```

## Best Practices

1. **Initialize Once**: Call `reportWebVitals()` only once per page load
2. **Client-Side Only**: Always use in a client component ('use client')
3. **Early Initialization**: Call in root layout for accurate metrics
4. **Monitor Trends**: Use Sentry to track performance over time
5. **Set Alerts**: Configure Sentry alerts for poor performance thresholds

## Troubleshooting

### Metrics Not Appearing in Sentry

1. Check `NEXT_PUBLIC_SENTRY_DSN` is set
2. Verify Sentry is initialized (`sentry.client.config.ts`)
3. Check browser console for errors
4. Ensure `@sentry/nextjs` is installed

### No Console Logs in Development

- Console logs only appear with `NODE_ENV=development`
- Check that `reportWebVitals()` is called in a client component

### SSR Errors

- Ensure `reportWebVitals()` is called in `useEffect` or a client component
- The function safely returns early on server-side

## Resources

- [Web Vitals](https://web.dev/vitals/)
- [Core Web Vitals](https://web.dev/articles/vitals)
- [Sentry Performance Monitoring](https://docs.sentry.io/product/performance/)
- [Google Analytics 4 Events](https://developers.google.com/analytics/devguides/collection/ga4/events)
