Imported from venil7/assets_client (
AGENTS.md). Install upstream withnpx skills add venil7/assets_client. Copyright stays with the author.
AI Agent Instructions for Assets Client
Project Overview
Assets Client is a Flutter-based API client application for macOS and Android that displays customer net worth information including portfolios, individual assets, transactions, and financial metrics. The app features a modern, slick UI with data visualization showing portfolio daily changes.
Target Platforms
- macOS (desktop)
- Android (mobile)
Key Features
- User Authentication: API server URL configuration → username/password login → JWT token-based auth
- Portfolio Management: Display user's portfolio and asset composition
- Transactions: Show buy/sell transaction history with details
- Data Visualization: Graphs depicting portfolio daily changes and trends
- Metadata: Display profit/loss and other financial metrics
Architecture & Technology Stack
Architecture Pattern: Clean Architecture + BLoC
The app should follow Clean Architecture with BLoC for state management:
- Presentation Layer: Flutter UI widgets, screens, pages
- Domain Layer: Business entities, repository interfaces, use cases
- Data Layer: API clients, repositories, data sources (local & remote)
- BLoC Layer: Business Logic Components managing state and events
Recommended Dependencies
State Management:
flutter_bloc: ^8.1.0+- BLoC pattern implementationequatable: ^2.0.0+- Value equality for BLoC events/states
Networking:
dio: ^5.0.0+- HTTP client with interceptors for JWT tokensretrofit: ^4.0.0+- REST client code generation
Local Storage:
hive: ^2.2.0+- Local key-value storage for API URL and JWT tokenshive_flutter: ^1.1.0+
Data Visualization:
fl_chart: ^0.63.0+- Charts and graphs for portfolio visualizationintl: ^0.19.0+- Internationalization (date/time formatting)
UI & UX:
google_fonts: ^6.0.0+- Modern typographyflutter_native_splash: ^2.3.0+- Native splash screens
Utilities:
freezed_annotation: ^2.4.0+&freezed: ^2.4.0+(dev) - Code generation for modelsjson_serializable: ^6.7.0+(dev) - JSON serialization code generationbuild_runner: ^2.4.0+(dev) - Code generation runner
Project Structure
lib/
├── main.dart # App entry point
├── config/
│ ├── routes.dart # Navigation routing
│ └── theme.dart # App theming (colors, typography)
├── core/
│ ├── constants/ # App-wide constants
│ ├── errors/ # Custom exceptions
│ └── network/
│ └── interceptors.dart # JWT token handling
├── features/
│ ├── auth/
│ │ ├── data/
│ │ │ ├── datasources/ # API calls, local storage
│ │ │ ├── models/ # JSON serializable models
│ │ │ └── repositories/ # Repository implementations
│ │ ├── domain/
│ │ │ ├── entities/ # Pure Dart classes
│ │ │ ├── repositories/ # Repository interfaces
│ │ │ └── usecases/ # Business logic
│ │ └── presentation/
│ │ ├── bloc/ # BLoC for auth state
│ │ ├── pages/ # Auth screens (login, setup)
│ │ └── widgets/ # Auth-related UI components
│ ├── portfolio/
│ │ ├── data/
│ │ ├── domain/
│ │ └── presentation/
│ ├── assets/
│ │ ├── data/
│ │ ├── domain/
│ │ └── presentation/
│ └── transactions/
│ ├── data/
│ ├── domain/
│ └── presentation/
└── shared/
├── widgets/ # Reusable UI components
└── utils/ # Helper functions
server URLs and authentication
The application is an API client, hence it can connect to a compatible API that is often selfhosted, or may be available on the internet (refer to API.md) for the atual API endpoints. Therefore it is assumed that an app will store an API base url (eg http://localhost:4020/api/v1 ) base url before it lets user login and communicate with it. The user authentocates with the chosen API via appropriate login endpoint where they supply username and passowrd, which returns a JWT token, along with the information of when it needs to be refreshed. The app stores a JWT token against username, but never the actual password. JWT among other things encodes when it expires. if API url, username and valid jwt are present usеr is considered to be logged in. All subsequent requests are made with JWT attached as bearer token.
Setup Commands
# Install dependencies
flutter pub get
# Generate code (models, BLoC, networking)
flutter pub run build_runner build --delete-conflicting-outputs
# Run on macOS
flutter run -d macos
# Run on Android
flutter run -d android
# Run tests
flutter test
Code Generation
When modifying models with @freezed or @JsonSerializable:
flutter pub run build_runner build --delete-conflicting-outputs
For continuous development with file watching:
flutter pub run build_runner watch --delete-conflicting-outputs
API Integration
the app communicates with the API using api_client.dart, most requests require JWT token , that is requested via login, and stored until it expires
Authentication Endpoints
- Server Setup: User provides API server base URL
- Login:
POST /auth/login- username/password → JWT token - Token Refresh:
POST /auth/refresh- maintain session
Data Endpoints (Expected structure)
- Portfolio:
GET /portfolio- user's current portfolio - Assets:
GET /assets- individual asset details - Transactions:
GET /transactions- buy/sell history - Metrics:
GET /metrics- profit/loss, daily changes
JWT Token Handling
- Storage: Tokens stored securely using Hive
- Interceptor: Dio interceptor automatically attaches JWT to requests
- Refresh: Automatic token refresh on 401 responses
UI/UX Guidelines
Design Principles
- Modern & Slick: Use Material Design 3 (Material 3 support in Flutter)
- Dark Mode: Support both light and dark themes
- Responsive: Adapt layouts for macOS (larger screens) and Android (varied sizes)
- Smooth Animations: Use Flutter's animation widgets for polished transitions
Key Screens
- Server Setup Screen: Input API server URL
- Login Screen: Username/password authentication
- Dashboard: Portfolio overview with key metrics
- Portfolio Details: Asset breakdown and composition
- Charts: Portfolio value over time (daily changes)
- Transactions: Transaction history with filters
- Settings: API URL, logout, app preferences
Chart Implementation
Use fl_chart for:
- Line Charts: Portfolio value over time (daily changes)
- Pie/Doughnut Charts: Asset allocation breakdown
- Bar Charts: Performance comparisons
Data Models & Serialization
Use freezed and json_serializable for models:
import 'package:freezed_annotation/freezed_annotation.dart';
part 'user.freezed.dart';
part 'user.g.dart';
@freezed
class User with _$User {
const factory User({
required String id,
required String username,
required String email,
}) = _User;
factory User.fromJson(Map<String, Object?> json) =>
_$UserFromJson(json);
}
All models should be immutable using @freezed.
State Management (BLoC)
BLoC Pattern for Features
Each feature (auth, portfolio, etc.) has its own BLoC:
- Events: User actions (e.g.,
LoginRequested,LogoutRequested) - States: UI states (e.g.,
AuthInitial,AuthLoading,AuthSuccess) - Transitions: How events transform states
Example BLoC usage in UI:
BlocBuilder<AuthBloc, AuthState>(
builder: (context, state) {
if (state is AuthLoading) return LoadingWidget();
if (state is AuthSuccess) return Dashboard();
if (state is AuthFailure) return ErrorWidget(state.message);
return LoginScreen();
},
)
Error Handling
Exception Hierarchy
AppException (abstract)
├── AuthException
│ ├── InvalidCredentialsException
│ └── TokenExpiredException
├── NetworkException
│ ├── ConnectionTimeoutException
│ └── ServerException
└── ValidationException
BLoC emits Failure states with user-friendly error messages.
Testing Strategy
do not run api_client_test unless specifically asked, as it requires a running backend
Unit Tests
- Models: Serialization/deserialization tests
- Use Cases: Business logic tests with mocked repositories
- Repositories: Data source interaction tests
Widget Tests
- Screens: UI rendering and interaction
- Forms: Input validation and submission
- Charts: Data visualization accuracy
Integration Tests
- Authentication Flow: Login → token storage → API calls
- Portfolio Loading: Fetch and display data
Test commands:
flutter test # All tests
flutter test --coverage # With coverage report
Platform-Specific Considerations
macOS
- Window Size: Adapt UI for desktop (larger screen space)
- Keyboard Navigation: Support tab navigation
- Menu Bar: Consider platform-specific menu integration
- File Paths: Use path providers for configuration storage
- Target: Requires macOS 10.13 or higher
Android
- Permissions: Request camera/storage if needed
- Screen Sizes: Handle various phone sizes and orientations
- Back Navigation: Implement proper back button handling
- Battery: Optimize background processes
- Target: Minimum Android API 21+
Key Development Patterns
Provider Pattern for Shared State
Use BlocProvider for global BLoCs:
MultiBlocProvider(
providers: [
BlocProvider(create: (_) => AuthBloc()),
BlocProvider(create: (_) => PortfolioBloc()),
],
child: const MyApp(),
)
Routing Architecture
- Use named routes with
RouteGeneratorfor type-safe navigation - BLoC can trigger navigation through context.read()
Network Interceptor Pattern
Dio interceptor handles:
- JWT token injection in headers
- Token refresh on 401 responses
- Request/response logging (debug mode)
- Error transformation to app exceptions
Common Development Tasks
Adding a New Feature
- consider reusing some existing funxtionality, if relevant
- Create folder structure under
lib/features/{feature}/ - Start with domain layer (entities, repository interfaces)
- Implement data layer (models, datasources, repository)
- Add BLoC (events, states, logic)
- Create presentation layer (pages, widgets, bloc listener/builder)
- Add routing and theme support
Adding a New API Endpoint
- Add method to API datasource (Retrofit)
- Update repository implementation
- Add use case if needed
- Create/update corresponding BLoC events and states
- Update presentation layer to use new state
Debugging
- Flutter DevTools:
flutter pub global activate devtools && devtools - Dio Logging: Enable in network config for request/response logs
- BLoC Logger: Use
flutter_blocobserver for state transitions - Hive Inspector: View local storage data
Code Quality & Linting
- Analyzer: Follows
flutter_lints: ^6.0.0rules - Format: Run
flutter format .before committing - Lint: Run
flutter analyzeto check code quality - Tests: Maintain >80% code coverage for critical features
Build & Release
macOS Build
flutter build macos --release
Output: build/macos/Build/Products/Release/assets_client.app
Android Build
flutter build apk --target-platform android-arm64 --split-per-abi
Requires keystore configuration for signing.
Important Notes for AI Agents
- always use caveman skill make sure to use Caveman skill
- Always generate code: After modifying models or adding new features, run
build_runnerto generate serialization/deserialization code - BLoC for state: Every feature should have a BLoC managing its state
- Clean Architecture: Separate concerns across data, domain, and presentation layers, reuse existing functionality where appropriate, avoid code duplication
- Error handling: Transform API errors into appropriate BLoC failure states
- Immutability: Use
@freezedfor all data models - Testing: Write tests for business logic and critical UI flows
- Assets & Localization: When adding assets, update
pubspec.yamland rebuild - Platform checks: Consider macOS vs Android differences in UI and performance