frosty/CLAUDE.md
Tommy Chow da2eeee518 update claude and copilot instructions for accuracy
- fix global stores documentation (add GlobalAssetsStore location, remove UserStore)
- correct error handling docs (typed exceptions via BaseApiClient, not Future.error)
- add missing lint rules (avoid_redundant_argument_values, unnecessary_parenthesis)
- fix emote factory methods (add all 4: fromTwitch, fromBTTV, fromFFZ, from7TV)
- update build_runner commands to modern dart run syntax
- add MobX reactions examples and API architecture section
- align commit convention with actual repo style (lowercase, no prefixes)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-11 04:26:05 -08:00

5.7 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Development Workflow

Plan Mode: When in plan mode, interview thoroughly before coding:

  • Ask detailed questions about technical implementation, UI/UX concerns, tradeoffs, and edge cases
  • Continue asking questions until all requirements and non-obvious decisions are clear
  • Don't begin implementation until all important details are resolved

Pattern Consistency: When implementing new code:

  • Search the codebase to find existing usages and implementations
  • Prefer following established patterns, styles, and practices for consistency

Development Commands

Common Commands:

  • flutter pub get - Install dependencies
  • flutter run --dart-define=clientId=YOUR_CLIENT_ID --dart-define=secret=YOUR_CLIENT_SECRET - Run with Twitch API credentials
  • flutter analyze - Run static analysis and lint checks
  • flutter test - Run all tests
  • flutter build apk / flutter build ios - Build release binaries

Code Generation (required after changing MobX stores or @JsonSerializable models):

  • dart run build_runner build - Generate once
  • dart run build_runner build --delete-conflicting-outputs - Force rebuild all
  • dart run build_runner watch - Watch mode for development

Architecture Overview

State Management: MobX with code generation. All stores end with Store and have corresponding .g.dart generated files.

Key Directories:

  • lib/screens/ - UI screens organized by feature (home, channel, settings, onboarding)
    • Each screen has its own MobX stores in a stores/ subdirectory
  • lib/models/ - Data models with JSON serialization (uses .g.dart files)
  • lib/apis/ - API services for Twitch, BTTV, FFZ, and 7TV
  • lib/widgets/ - Reusable UI components
  • lib/utils/ - Utility modules including context extensions

Main Application Flow:

  1. App starts in main.dart with Firebase initialization and dependency injection via Provider
  2. Authentication handled by AuthStore using Twitch OAuth
  3. Settings persisted via SettingsStore with SharedPreferences and MobX autorun()
  4. API services share a common Dio HTTP client for efficient connection reuse

Global Stores (injected via Provider in main.dart):

  • AuthStore (lib/screens/settings/stores/) - Authentication state and token management
  • SettingsStore (lib/screens/settings/stores/) - User preferences with automatic persistence via MobX autorun()
  • GlobalAssetsStore (lib/stores/) - Shared cache for global emotes and badges across all chat tabs

HTTP & Auth: Centralized Dio client (DioClient.createClient()) with connection pooling and optimized timeouts. TwitchAuthInterceptor auto-injects auth headers for Twitch API URLs. UnauthorizedInterceptor catches 401 errors for token refresh. Two-tier token system: default app token + optional user token in Flutter Secure Storage.

MobX Store Implementation

Store Pattern: All stores follow StoreBase with _$StoreName pattern:

class SomeStore = SomeStoreBase with _$SomeStore;

abstract class SomeStoreBase with Store {
  @observable
  var someValue = '';

  @action
  void updateValue(String value) => someValue = value;

  @computed
  String get derivedValue => someValue.toUpperCase();
}

MobX Reactions (for side effects and persistence):

// Auto-save settings whenever they change (in main.dart)
autorun((_) => prefs.setString('settings', jsonEncode(settingsStore)));

// React to specific state changes
reaction((_) => authStore.isLoggedIn, (_) => _selectedIndex = 0);

Chat System Architecture

  • Real-time IRC: WebSocket connection to Twitch IRC with custom IRCMessage parsing
  • Third-party Emotes: Asynchronous loading of BTTV, FFZ, and 7TV assets via dedicated APIs
  • Message Management: 5000 message limit with 20% batch removal optimization
  • Assets Store: ChatAssetsStore manages channel-specific emotes/badges

Additional Patterns

Emote Architecture: Base Emote class with platform-specific factories: Emote.fromTwitch(), Emote.fromBTTV(), Emote.fromFFZ(), Emote.from7TV().

Custom Cache Manager: Uses 30-day stale period and 10k max objects. CustomCacheManager.removeOrphanedCacheFiles() runs on startup to clean files not in database.

Secure Storage Cleanup: First-run detection clears Flutter Secure Storage to handle Android/iOS uninstall edge case where secure storage persists but app data is wiped.

API Architecture

BaseApiClient Pattern: All API services (TwitchApi, BTTVApi, FFZApi, SevenTVApi) extend BaseApiClient which provides:

  • Generic GET/POST/PUT/DELETE methods with centralized error handling
  • Automatic conversion of DioException to typed exceptions

Exception Hierarchy (in lib/apis/base_api_client.dart):

  • ApiException - Base class for all API errors
  • NetworkException - Connection errors (no internet)
  • TimeoutException - Request timeouts
  • ServerException - 5xx server errors
  • NotFoundException - 404 errors
  • UnauthorizedException - 401 errors (triggers token refresh)

Code Style

Lint Rules (from analysis_options.yaml):

  • prefer_single_quotes, always_use_package_imports, require_trailing_commas
  • prefer_final_locals, prefer_final_in_for_each, avoid_redundant_argument_values
  • directives_ordering, avoid_void_async, always_declare_return_types, unnecessary_parenthesis

Other:

  • Generated .g.dart files must be committed alongside source changes

Commit Convention

Commits use lowercase, descriptive messages without prefixes (e.g., fix landscape bottom padding in chat bottom bar, add swipe pip gesture support). Keep commits tightly scoped.