# Feature Architecture: Modes vs Feature Flags ## The Problem Your current system has two overlapping concepts that conflict: - **Feature Flags** (`features.config.ts`) - Controls individual features - **App Modes** (`NEXT_PUBLIC_GRIDPILOT_MODE`) - Controls overall platform visibility This creates confusion because: 1. Development shows only landing page but feature config says everything is enabled 2. It's unclear which system controls what 3. Teams don't know when to use mode vs feature flag ## The Solution: Clear Separation ### **Two-Tier System** ``` ┌─────────────────────────────────────────┐ │ APP MODE (Tier 1) │ │ Controls WHAT the platform shows │ │ - pre-launch: Landing page only │ │ - alpha: Full platform access │ │ - beta: Production-ready features │ └─────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────┐ │ FEATURE FLAGS (Tier 2) │ │ Controls WHICH features are enabled │ │ - Individual feature toggles │ │ - Rollout control │ │ - A/B testing │ └─────────────────────────────────────────┘ ``` ### **Mode = Platform Scope** **App Mode defines what the entire platform can do:** - **`pre-launch`**: "We're not ready yet" - Shows: Landing page, Discord CTA, FAQ - Hides: All navigation, dashboard, leagues, teams, races - Purpose: Marketing/teaser phase - **`alpha`**: "Early access for testers" - Shows: Everything + alpha badges - Purpose: Internal testing, early adopters - All features enabled by default - **`beta`**: "Public beta" - Shows: Production features only - Purpose: Gradual rollout to real users - Features controlled individually ### **Feature Flags = Feature Control** **Feature flags control individual features within a mode:** ```typescript // In alpha mode, all features are ON by default // But you can still disable specific ones for testing { "platform.dashboard": "enabled", "platform.leagues": "enabled", "platform.teams": "disabled", // Testing without teams "sponsors.portal": "enabled", "admin.dashboard": "enabled" } ``` ## Simple Mental Model ### **For Developers: "The Restaurant Analogy"** ``` APP MODE = Restaurant State ├── "Closed" (pre-launch) → Only show entrance/menu ├── "Soft Opening" (alpha) → Full menu, everything available └── "Grand Opening" (beta) → Full menu, but some items may be 86'd FEATURE FLAGS = Menu Items ├── Each dish can be: Available / 86'd / Coming Soon ├── Works within whatever restaurant state you're in └── Lets you control individual items precisely ``` ### **Decision Tree** ``` Question: "What should I use?" │ ├─ "Is the platform ready for ANY users?" │ ├─ No → Use APP MODE = pre-launch │ └─ Yes → Continue... │ ├─ "Are we in testing or production?" │ ├─ Testing → Use APP MODE = alpha │ └─ Production → Use APP MODE = beta │ └─ "Do I need to control a specific feature?" └─ Yes → Use FEATURE FLAGS (regardless of mode) ``` ## Implementation Rules ### **Rule 1: Mode Controls Visibility** ```typescript // ❌ WRONG: Using feature flags to hide entire platform { "platform": { "dashboard": "disabled", "leagues": "disabled", "teams": "disabled" } } // ✅ CORRECT: Use mode for platform-wide visibility // NEXT_PUBLIC_GRIDPILOT_MODE=pre-launch ``` ### **Rule 2: Feature Flags Control Granularity** ```typescript // ✅ CORRECT: Feature flags for fine-grained control { "platform": { "dashboard": "enabled", "leagues": "enabled", "teams": "enabled", // But specific team features... "teams.create": "disabled", // ...can be toggled "teams.delete": "coming_soon" } } ``` ### **Rule 3: Alpha Mode = Auto-Enable** ```typescript // In alpha mode, ALL features are enabled automatically // Feature flags can only DISABLE, not enable // This eliminates configuration complexity // Feature flag service in alpha mode: if (mode === 'alpha') { return new FeatureFlagService([ 'all', 'features', 'enabled', 'by', 'default' ]); } ``` ## Migration Path ### **Current State (Confusing)** ``` Development: - Mode: pre-launch (default) - Features: All enabled in config - Result: Shows landing page only ❌ Why? Because mode overrides feature config ``` ### **Target State (Clear)** ``` Development: - Mode: alpha (explicit) - Features: All auto-enabled - Result: Full platform with alpha badges ✅ Production: - Mode: beta - Features: Controlled individually - Result: Gradual rollout ✅ ``` ## Configuration Examples ### **Simple Mode Config** ```typescript // apps/website/.env.development NEXT_PUBLIC_GRIDPILOT_MODE=alpha // apps/website/.env.production NEXT_PUBLIC_GRIDPILOT_MODE=beta ``` ### **Feature Flags (Only When Needed)** ```typescript // Only override defaults when necessary // apps/api/src/config/features.config.ts { production: { platform: { dashboard: 'enabled', leagues: 'enabled', teams: 'enabled', races: 'enabled', leaderboards: 'enabled' }, sponsors: { portal: 'enabled', dashboard: 'enabled', management: 'disabled' // Not ready yet } } } ``` ## Benefits 1. **No Confusion**: Clear separation of concerns 2. **Less Config**: Alpha mode needs zero feature config 3. **Easy Onboarding**: New devs just set mode=alpha 4. **Powerful Control**: Feature flags still available when needed 5. **Backward Compatible**: Existing code works with new concept ## Quick Reference | Scenario | Mode | Feature Flags | Result | |----------|------|---------------|--------| | Local dev | `alpha` | None needed | Full platform | | CI/CD tests | `alpha` | None needed | Full platform | | Staging | `beta` | Some disabled | Controlled rollout | | Production | `beta` | Gradual enable | Public launch | | Marketing site | `pre-launch` | N/A | Landing page only | This eliminates the contradiction and gives you clear power: **Mode for scope, flags for granularity.**