- 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>
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 dependenciesflutter run --dart-define=clientId=YOUR_CLIENT_ID --dart-define=secret=YOUR_CLIENT_SECRET- Run with Twitch API credentialsflutter analyze- Run static analysis and lint checksflutter test- Run all testsflutter build apk/flutter build ios- Build release binaries
Code Generation (required after changing MobX stores or @JsonSerializable models):
dart run build_runner build- Generate oncedart run build_runner build --delete-conflicting-outputs- Force rebuild alldart 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
- Each screen has its own MobX stores in a
lib/models/- Data models with JSON serialization (uses .g.dart files)lib/apis/- API services for Twitch, BTTV, FFZ, and 7TVlib/widgets/- Reusable UI componentslib/utils/- Utility modules including context extensions
Main Application Flow:
- App starts in
main.dartwith Firebase initialization and dependency injection via Provider - Authentication handled by
AuthStoreusing Twitch OAuth - Settings persisted via
SettingsStorewith SharedPreferences and MobXautorun() - 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 managementSettingsStore(lib/screens/settings/stores/) - User preferences with automatic persistence via MobXautorun()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
IRCMessageparsing - 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:
ChatAssetsStoremanages 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
DioExceptionto typed exceptions
Exception Hierarchy (in lib/apis/base_api_client.dart):
ApiException- Base class for all API errorsNetworkException- Connection errors (no internet)TimeoutException- Request timeoutsServerException- 5xx server errorsNotFoundException- 404 errorsUnauthorizedException- 401 errors (triggers token refresh)
Code Style
Lint Rules (from analysis_options.yaml):
prefer_single_quotes,always_use_package_imports,require_trailing_commasprefer_final_locals,prefer_final_in_for_each,avoid_redundant_argument_valuesdirectives_ordering,avoid_void_async,always_declare_return_types,unnecessary_parenthesis
Other:
- Generated
.g.dartfiles 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.