7.1 KiB
AGENTS.md
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
Dead Code Cleanup: When new code replaces or supersedes existing functionality:
- Identify and remove anything the new code makes redundant
- Clean up any remaining references or imports to the removed code
Parallelization: Favor parallel tool calls and subagents whenever tasks are independent (e.g., reading multiple files, running searches, exploring different parts of the codebase). Don't do things sequentially when they can be done concurrently.
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 test test/path/to/test.dart- Run a single test fileflutter 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
Generated .g.dart files are excluded from linting but must be committed to source control. Never edit .g.dart files directly — they are overwritten by build_runner.
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)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 extensionslib/services/- Application services (e.g., shared timer service)
Screen Organization: lib/screens/{feature}/ contains {feature}.dart (main UI), stores/ subdirectory with MobX stores, and feature sub-components.
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()UserStore(lib/screens/settings/stores/) - Current user profile dataGlobalAssetsStore(lib/stores/) - Shared cache for global emotes and badges across all chat tabs
HTTP & API Architecture
Shared HTTP Client: Single Dio instance configured in DioClient.createClient() with:
- Connection pooling and keep-alive headers for efficiency
- Optimized timeouts: 8s connect, 15s receive, 10s send
- Frosty User-Agent header for Twitch API compatibility
Authentication Interceptor: TwitchAuthInterceptor automatically injects auth headers for Twitch API URLs. UnauthorizedInterceptor catches 401 errors for token refresh.
Two-tier Token System: Default app token for unauthenticated requests + optional user token in Flutter Secure Storage.
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: ApiException base class with NetworkException, TimeoutException, ServerException, NotFoundException, UnauthorizedException (see lib/apis/base_api_client.dart).
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 - User Interaction: Blocking, reporting, and moderation capabilities
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.
Authentication Flow:
- OAuth via WebView with custom JavaScript injection for seamless Twitch login
- Token storage in FlutterSecureStorage
- Auto-refresh and validation logic in
AuthStore
Code Style
Common lint mistakes to avoid:
- Always use package imports, not relative imports (
import 'package:frosty/...') - Always include trailing commas in argument lists and widget trees
- Use single quotes for strings
Full lint rules are enforced by flutter analyze — run it after making changes to catch issues early.
Testing
Tests live in test/ mirroring the lib/ structure:
test/models/- Model unit tests (badges, emotes, IRC parsing)test/fixtures/- Shared test data (e.g., IRC message fixtures)test/regex_test.dart,test/utils_test.dart- Utility tests
Run with flutter test or flutter test test/path/to/file.dart for a single file.
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.