---
created: 2026-03-12
source: Rivet
tags: [agent-archive, rivet]
---

# Console.log Cleanup Implementation Plan

## Executive Summary

**Current State**: The $50 app has 87 `console.log` statements across 44 files, exposing sensitive data (user IDs, match details, internal logic) to browser consoles in production.

**Goal**: Replace all `console.log` statements with a structured logging solution that:
- Silences logs in production (security/privacy)
- Maintains development/debugging capabilities
- Supports both server-side (API routes) and client-side (React components) logging
- Enables production debugging when needed
- Integrates with error tracking (optional)

## 1. Recommended Logging Library: Pino (Already Installed)

**Why Pino over Winston or custom solution:**

1. **Already in dependencies**: `pino@10.3.0` and `pino-pretty@13.1.3` are already installed
2. **Performance**: Pino is 5-10x faster than Winston in benchmarks
3. **Bundle size**: Minimal client-side footprint (~17KB vs Winston's ~200KB)
4. **Next.js compatibility**: Works with both server and client components
5. **Structured logging**: JSON-first approach, ideal for production log aggregation
6. **Browser support**: Built-in browser transport with `pino/browser`

**Current logger exists**: `src/lib/logger.ts` already implements Pino with environment-based configuration.

## 2. Logger Structure: Dual-Mode Architecture

### Server-side Logger (API routes, server components)
```typescript
// src/lib/server-logger.ts (new)
import pino from 'pino';

const isDevelopment = process.env.NODE_ENV === 'development';

export const serverLogger = pino({
  level: isDevelopment ? 'debug' : 'warn',
  transport: isDevelopment ? {
    target: 'pino-pretty',
    options: {
      colorize: true,
      translateTime: 'SYS:standard',
      ignore: 'pid,hostname',
    },
  } : undefined,
  // Production: Add destination for log aggregation (optional)
  ...(process.env.NODE_ENV === 'production' && process.env.LOG_DESTINATION 
    ? { transport: { target: process.env.LOG_DESTINATION } }
    : {}),
});

// Convenience methods
export const log = {
  debug: (msg: string, data?: any) => serverLogger.debug(data, msg),
  info: (msg: string, data?: any) => serverLogger.info(data, msg),
  warn: (msg: string, data?: any) => serverLogger.warn(data, msg),
  error: (msg: string, data?: any) => serverLogger.error(data, msg),
};
```

### Client-side Logger (React components, browser)
```typescript
// src/lib/client-logger.ts (new)
import pino from 'pino';

const isDevelopment = process.env.NODE_ENV === 'development';

export const clientLogger = pino({
  level: isDevelopment ? 'debug' : 'silent', // 'silent' disables all logs
  browser: {
    asObject: true,
    write: (o) => {
      // In development, output to console with formatting
      if (isDevelopment) {
        const { level, msg, ...rest } = o;
        const levelMap = { 10: 'trace', 20: 'debug', 30: 'info', 40: 'warn', 50: 'error', 60: 'fatal' };
        const levelName = levelMap[level as keyof typeof levelMap] || 'info';
        
        // Color-coded console output
        const colors = {
          trace: 'color: gray',
          debug: 'color: cyan',
          info: 'color: green',
          warn: 'color: orange',
          error: 'color: red',
          fatal: 'color: darkred',
        };
        
        console.log(`%c[${levelName.toUpperCase()}] ${msg}`, colors[levelName as keyof typeof colors], rest);
      }
      // In production: silent OR send to monitoring service
      else if (process.env.NEXT_PUBLIC_SENTRY_DSN) {
        // Optional: Send to Sentry or other monitoring
        // window.Sentry?.captureMessage(msg, { level, extra: rest });
      }
    },
  },
});

// React hook for component logging
export const useLogger = () => {
  const logger = clientLogger;
  
  return {
    debug: (msg: string, data?: any) => logger.debug(data, msg),
    info: (msg: string, data?: any) => logger.info(data, msg),
    warn: (msg: string, data?: any) => logger.warn(data, msg),
    error: (msg: string, data?: any) => logger.error(data, msg),
  };
};
```

### Unified Logger (Backward compatibility)
```typescript
// src/lib/logger.ts (enhance existing)
import { serverLogger } from './server-logger';
import { clientLogger } from './client-logger';

// Detect environment
const isServer = typeof window === 'undefined';

export const logger = isServer ? serverLogger : clientLogger;

// Convenience methods matching console.log API
export const log = {
  debug: (msg: string, ...args: any[]) => {
    const data = args.length === 1 ? args[0] : args;
    logger.debug(data, msg);
  },
  info: (msg: string, ...args: any[]) => {
    const data = args.length === 1 ? args[0] : args;
    logger.info(data, msg);
  },
  warn: (msg: string, ...args: any[]) => {
    const data = args.length === 1 ? args[0] : args;
    logger.warn(data, msg);
  },
  error: (msg: string, ...args: any[]) => {
    const data = args.length === 1 ? args[0] : args;
    logger.error(data, msg);
  },
};

export default logger;
```

## 3. Migration Strategy

### Phase 1: Audit & Categorization (Week 1)
1. **Run audit script** to identify all console.log statements:
   ```bash
   # Find all console.log usage
   grep -rn "console\." /home/ccuser/the-50-dollar-app/src --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" > console-audit.txt
   
   # Categorize by:
   # - Security-sensitive (user IDs, PII, match details)
   # - Debug-only (development helpers)
   # - Error handling
   # - Performance monitoring
   ```

2. **Priority classification**:
   - **Critical**: Security-sensitive logs (user IDs, match details) - fix immediately
   - **High**: Production-facing logs (API routes, public pages)
   - **Medium**: Admin/internal pages
   - **Low**: Test files, development-only scripts

### Phase 2: Replacement Patterns (Week 2-3)

#### Pattern 1: Simple console.log → logger.debug/info
```typescript
// BEFORE
console.log('User logged in:', userId);
console.log('API response:', data);

// AFTER
import { log } from '@/lib/logger';
log.debug('User logged in', { userId });
log.info('API response received', { data });
```

#### Pattern 2: Error logging
```typescript
// BEFORE
console.error('Payment failed:', error);
console.warn('Cache miss for user:', userId);

// AFTER
import { log } from '@/lib/logger';
log.error('Payment failed', { error, userId });
log.warn('Cache miss', { userId });
```

#### Pattern 3: Development-only logs
```typescript
// BEFORE
console.log('DEBUG: Component rendered with props:', props);

// AFTER
import { log } from '@/lib/logger';
if (process.env.NODE_ENV === 'development') {
  log.debug('Component rendered', { props });
}
```

#### Pattern 4: Performance monitoring
```typescript
// BEFORE
console.time('apiCall');
// ... API call
console.timeEnd('apiCall');

// AFTER
import { log } from '@/lib/logger';
const start = performance.now();
// ... API call
const duration = performance.now() - start;
log.debug('API call completed', { durationMs: duration, endpoint: '/api/data' });
```

### Phase 3: Automated Replacement (Optional)
Create a codemod script for bulk replacement:
```javascript
// scripts/replace-console.js
const fs = require('fs');
const path = require('path');

// Patterns to replace
const patterns = [
  { regex: /console\.log\((['"`])(.*?)\1(?:,\s*(.*))?\)/g, replacement: 'log.info("$2", $3)' },
  { regex: /console\.error\((['"`])(.*?)\1(?:,\s*(.*))?\)/g, replacement: 'log.error("$2", $3)' },
  { regex: /console\.warn\((['"`])(.*?)\1(?:,\s*(.*))?\)/g, replacement: 'log.warn("$2", $3)' },
];
```

### Phase 4: Validation & Testing (Week 4)
1. **Security audit**: Verify no sensitive data leaks to browser console
2. **Development testing**: Ensure logs work in dev mode
3. **Production build**: Verify logs are silent
4. **Performance check**: No bundle size regression

## 4. Environment-Based Configuration

### Development (.env.local)
```env
NODE_ENV=development
LOG_LEVEL=debug
# Optional: Local log file
LOG_FILE=logs/app.log
```

### Production (.env.production)
```env
NODE_ENV=production
LOG_LEVEL=warn  # Only warnings and errors
# Optional: Remote logging service
LOG_DESTINATION=@logtail/pino  # For Better Stack
# or
LOG_DESTINATION=pino-sentry-transport
```

### Client-side Environment Variables
```env
# .env.local (development)
NEXT_PUBLIC_LOG_LEVEL=debug

# .env.production
NEXT_PUBLIC_LOG_LEVEL=silent
```

### Conditional Logging Helper
```typescript
// src/lib/log-utils.ts
export const shouldLog = (level: 'debug' | 'info' | 'warn' | 'error') => {
  const envLevel = process.env.NEXT_PUBLIC_LOG_LEVEL || 'warn';
  const levels = { debug: 0, info: 1, warn: 2, error: 3, silent: 4 };
  return levels[level] >= levels[envLevel];
};

// Usage
if (shouldLog('debug')) {
  log.debug('Detailed debug info', sensitiveData);
}
```

## 5. Production Debugging Strategy

### Option A: Feature Flag Debugging
```typescript
// Enable via URL parameter ?debug=true
export const isDebugEnabled = () => {
  if (typeof window !== 'undefined') {
    const params = new URLSearchParams(window.location.search);
    return params.get('debug') === 'true' && 
           process.env.NODE_ENV === 'production';
  }
  return false;
};

// Usage
if (isDebugEnabled()) {
  log.info('Production debug mode enabled');
}
```

### Option B: User Role-Based Debugging
```typescript
// Only show logs for admin users
export const canUserSeeLogs = (userRole: string) => {
  return ['admin', 'developer'].includes(userRole) && 
         process.env.NODE_ENV === 'production';
};
```

### Option C: Remote Log Collection
```typescript
// Send logs to monitoring service in production
if (process.env.NODE_ENV === 'production' && process.env.NEXT_PUBLIC_SENTRY_DSN) {
  // Configure Pino to send to Sentry
  const transport = pino.transport({
    target: 'pino-sentry-transport',
    options: {
      sentry: {
        dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
      },
      minLevel: 30, // info and above
    },
  });
}
```

## 6. Sentry Integration (Optional)

### Benefits:
- Centralized error tracking
- Performance monitoring
- User session replay
- Log aggregation

### Setup:
```typescript
// src/lib/sentry-logger.ts
import * as Sentry from '@sentry/nextjs';
import pino from 'pino';

export const sentryLogger = pino({
  level: 'info',
  transport: {
    target: 'pino-sentry-transport',
    options: {
      sentry: {
        dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
        environment: process.env.NODE_ENV,
      },
      minLevel: 30, // Send info, warn, error, fatal
    },
  },
});

// Integrate with existing logger
export const createLoggerWithSentry = () => {
  const baseLogger = pino({
    level: process.env.NODE_ENV === 'development' ? 'debug' : 'info',
  });
  
  return {
    ...baseLogger,
    error: (obj: any, msg?: string) => {
      baseLogger.error(obj, msg);
      Sentry.captureException(obj instanceof Error ? obj : new Error(msg));
    },
  };
};
```

## 7. Implementation Timeline

### Week 1-2: Foundation
- Enhance existing logger with client/server separation
- Create migration scripts
- Update documentation

### Week 3-4: High-Priority Files
- Replace security-sensitive logs (user IDs, match details)
- Update API routes and authentication flows
- Fix error handling logs

### Week 5-6: Remaining Files
- Update React components
- Replace development/debug logs
- Update test files

### Week 7: Validation & Deployment
- Security audit
- Performance testing
- Deploy to staging
- Monitor for issues

## 8. Success Metrics

1. **Security**: Zero sensitive data in browser console in production
2. **Performance**: < 5% bundle size increase
3. **Developer Experience**: 
   - Clear logging in development
   - Easy debugging when needed
   - Consistent API across codebase
4. **Maintainability**: 
   - All logging centralized
   - Environment-aware configuration
   - Easy to add new log destinations

## 9. Risk Mitigation

| Risk | Mitigation |
|------|------------|
| Breaking existing debugging | Keep development logs fully functional |
| Performance impact | Use Pino (high performance), tree-shake in production |
| Missing critical logs | Gradual migration, peer review |
| Bundle size increase | Client logger only loads in dev, silent in prod |
| Learning curve | Provide examples, documentation |

## 10. Code Examples

### Server Component Usage
```typescript
// app/api/users/route.ts
import { log } from '@/lib/logger';

export async function GET(request: Request) {
  try {
    log.debug('Fetching users', { url: request.url });
    const users = await db.users.findMany();
    log.info('Users fetched', { count: users.length });
    return Response.json(users);
  } catch (error) {
    log.error('Failed to fetch users', { error });
    return Response.json({ error: 'Internal server error' }, { status: 500 });
  }
}
```

### Client Component Usage
```typescript
// components/UserProfile.tsx
'use client';
import { useLogger } from '@/lib/client-logger';

export function UserProfile({ userId }: { userId: string }) {
  const logger = useLogger();
  
  useEffect(() => {
    logger.debug('UserProfile mounted', { userId });
    
    return () => {
      logger.debug('UserProfile unmounted', { userId });
    };
  }, [userId, logger]);
  
  // Component logic...
}
```

### Error Boundary Usage
```typescript
// app/error.tsx
'use client';
import { log } from '@/lib/logger';

export default function ErrorBoundary({ error }: { error: Error }) {
  useEffect(() => {
    log.error('Error boundary caught error', { 
      error: error.message,
      stack: error.stack,
      component: 'ErrorBoundary'
    });
  }, [error]);
  
  // Error UI...
}
```

## Conclusion

The existing Pino logger provides an excellent foundation. The key improvements needed are:
1. **Client-side logger** that silences logs in production
2. **Security audit** to identify and fix sensitive data exposure
3. **Gradual migration** from console.log to structured logging
4. **Optional Sentry integration** for production monitoring

This plan balances security requirements with developer productivity, ensuring the app remains debuggable while protecting user data.