# Feature Architecture: API-Driven Feature Flags

## The Problem

Your previous system had two overlapping concepts that conflicted:
- **Feature Flags** (`features.config.ts`) - Controls individual features
- **App Modes** (`NEXT_PUBLIC_GRIDPILOT_MODE`) - Controls overall platform visibility

This created confusion because:
1. Development showed only landing page but feature config said everything was enabled
2. It's unclear which system controls what
3. Teams don't know when to use mode vs feature flag

## The Solution: API-Driven Features

### **Single Source of Truth: API**

All feature control now comes from the API `/features` endpoint:

```typescript
// API Response (from /features endpoint)
{
  "alpha_features": true,
  "platform.dashboard": true,
  "platform.leagues": true,
  "platform.teams": true,
  "sponsors.portal": true,
  // ... all other features
}
```

### **FeatureFlagService - The Bridge**

The `FeatureFlagService` is the **only** way to check feature availability:

```typescript
// ✅ CORRECT: Use FeatureFlagService
const service = await FeatureFlagService.fromAPI();
const isEnabled = service.isEnabled('platform.dashboard');

// ❌ WRONG: No more environment mode checks
const mode = process.env.NEXT_PUBLIC_GRIDPILOT_MODE; // REMOVED
```

### **How It Works**

1. **API Layer**: `features.config.ts` defines features per environment
2. **Service Layer**: `FeatureFlagService` fetches and caches features from API
3. **Client Layer**: Components use `FeatureFlagService` or `ModeGuard` for conditional rendering

## Implementation Rules

### **Rule 1: Always Use FeatureFlagService**

```typescript
// ✅ CORRECT: Use FeatureFlagService for all feature checks
import { FeatureFlagService } from '@/lib/feature/FeatureFlagService';

async function MyComponent() {
  const service = await FeatureFlagService.fromAPI();
  
  if (service.isEnabled('platform.dashboard')) {
    return <Dashboard />;
  }
  
  return <LandingPage />;
}
```

### **Rule 2: Use ModeGuard for Conditional Rendering**

```typescript
// ✅ CORRECT: Use ModeGuard for client-side conditional rendering
import { ModeGuard } from '@/components/shared/ModeGuard';

function Page() {
  return (
    <ModeGuard feature="platform.dashboard" fallback={<LandingPage />}>
      <Dashboard />
    </ModeGuard>
  );
}
```

### **Rule 3: Use Hooks for Client Components**

```typescript
// ✅ CORRECT: Use hooks in client components
import { useFeature, useFeatures } from '@/components/shared/ModeGuard';

function ClientComponent() {
  const hasDashboard = useFeature('platform.dashboard');
  const features = useFeatures(['platform.dashboard', 'platform.leagues']);
  
  if (!hasDashboard) return null;
  
  return <div>Dashboard Content</div>;
}
```

## Configuration Examples

### **API Configuration (features.config.ts)**

```typescript
// apps/api/src/config/features.config.ts
export const featuresConfig = {
  development: {
    // Alpha features enabled for development
    alpha_features: 'enabled',
    platform: {
      dashboard: 'enabled',
      leagues: 'enabled',
      teams: 'enabled',
      races: 'enabled',
    },
    sponsors: {
      portal: 'enabled',
    },
  },
  
  production: {
    // Gradual rollout in production
    alpha_features: 'disabled',
    platform: {
      dashboard: 'enabled',
      leagues: 'enabled',
      teams: 'enabled',
      races: 'enabled',
    },
    sponsors: {
      portal: 'coming_soon', // Not ready yet
    },
  },
};
```

### **No More Environment Variables**

```bash
# ❌ REMOVED
NEXT_PUBLIC_GRIDPILOT_MODE=alpha

# ✅ ONLY NEEDED
NEXT_PUBLIC_API_BASE_URL=http://localhost:3001
```

## Migration Path

### **Before (Confusing)**

```typescript
// apps/website/lib/mode.ts (DELETED)
export function getAppMode(): AppMode {
  const mode = process.env.NEXT_PUBLIC_GRIDPILOT_MODE;
  // ... complex logic
}

// apps/website/components/shared/ModeGuard.tsx (UPDATED)
// Used to check process.env.NEXT_PUBLIC_GRIDPILOT_MODE
// Now uses FeatureFlagService
```

### **After (Clear)**

```typescript
// apps/website/lib/feature/FeatureFlagService.ts
export class FeatureFlagService {
  static async fromAPI(): Promise<FeatureFlagService> {
    // Fetches from /features endpoint
    // Caches results
    // Provides simple isEnabled() method
  }
}

// apps/website/components/shared/ModeGuard.tsx (UPDATED)
// Uses FeatureFlagService for all feature checks
// No environment variables needed
```

## Benefits

1. **Single Source of Truth**: API controls all features
2. **No Confusion**: Clear separation between feature availability and platform scope
3. **Runtime Control**: Features can be changed without redeployment
4. **Type Safety**: Feature names are typed and validated
5. **Easy Testing**: Mock the API response for tests

## Quick Reference

| Scenario | Implementation | Result |
|----------|---------------|--------|
| Local dev | API returns all enabled features | Full platform |
| CI/CD tests | API returns all enabled features | Full platform |
| Staging | API returns controlled features | Controlled rollout |
| Production | API returns production features | Public launch |
| Feature flags | API config for granular control | Fine-tuned features |

## Files Changed

- ✅ `apps/website/lib/config/env.ts` - Removed `NEXT_PUBLIC_GRIDPILOT_MODE`
- ✅ `apps/website/lib/mode.ts` - **DELETED**
- ✅ `apps/website/lib/mode.test.ts` - **DELETED**
- ✅ `apps/website/components/shared/ModeGuard.tsx` - Updated to use API
- ✅ `apps/website/env.d.ts` - Removed mode declaration
- ✅ All env example files - Updated to remove mode variable
- ✅ `apps/website/components/errors/ErrorAnalyticsDashboard.tsx` - Removed appMode
- ✅ `apps/website/components/dev/DebugModeToggle.tsx` - Removed appMode
- ✅ `apps/website/lib/infrastructure/ErrorReplay.ts` - Removed appMode

## Verification

Run these commands to verify the changes:

```bash
# Type check
npm run typecheck

# Lint
npm run lint

# Tests
npm run test

# Build
npm run build
```

All should pass without references to `NEXT_PUBLIC_GRIDPILOT_MODE` or the deleted mode files.