Soliplex Frontend Codebase Analysis
Last updated: January 2026
Note: File counts and structure in this document reflect the codebase as of the last update. Run
find lib -name "*.dart" | wc -lto get current counts.
1. Project Structure
frontend/
├── lib/ # Main Flutter app (~79 Dart files)
│ ├── main.dart # Entry point with ProviderScope
│ ├── app.dart # Root SoliplexApp widget
│ ├── core/ # Infrastructure layer
│ │ ├── auth/ # Authentication (14 files)
│ │ │ ├── auth_state.dart # Sealed class: Unauthenticated|Authenticated|AuthLoading|NoAuthRequired
│ │ │ ├── auth_provider.dart # Main auth notifier provider
│ │ │ ├── auth_notifier.dart # Auth state management
│ │ │ ├── auth_flow*.dart # Platform-specific OAuth flows (native, web)
│ │ │ ├── auth_storage*.dart # Platform-specific token storage (native, web)
│ │ │ └── oidc_issuer.dart # OIDC issuer management
│ │ ├── models/ # Core data models
│ │ │ ├── active_run_state.dart # Sealed class: IdleState|RunningState|CompletedState
│ │ │ └── app_config.dart # App configuration (baseUrl)
│ │ ├── providers/ # Riverpod state management (12 providers)
│ │ │ ├── api_provider.dart # SoliplexApi with HTTP transport
│ │ │ ├── active_run_provider.dart
│ │ │ ├── active_run_notifier.dart
│ │ │ ├── config_provider.dart
│ │ │ ├── rooms_provider.dart
│ │ │ ├── threads_provider.dart
│ │ │ ├── thread_message_cache.dart
│ │ │ ├── backend_health_provider.dart
│ │ │ ├── backend_version_provider.dart
│ │ │ ├── http_log_provider.dart
│ │ │ ├── package_info_provider.dart
│ │ │ └── quiz_provider.dart
│ │ ├── router/
│ │ │ └── app_router.dart # GoRouter (8 routes)
│ │ └── constants/
│ │ └── breakpoints.dart # Responsive breakpoints
│ ├── features/ # Feature screens
│ │ ├── auth/ # OAuth callback handler
│ │ ├── home/ # Backend URL configuration
│ │ ├── login/ # OIDC login UI
│ │ ├── rooms/ # Room list
│ │ ├── room/ # Room view with threads
│ │ ├── chat/ # Chat messaging (4 files)
│ │ ├── history/ # Thread list sidebar (3 files)
│ │ ├── inspector/ # HTTP traffic debugger (5 files)
│ │ └── settings/ # Settings screen
│ └── shared/ # Reusable components
│ ├── widgets/ # AppShell, AsyncValueHandler, etc.
│ └── utils/ # Date formatting, utilities
│
├── packages/soliplex_client/ # Pure Dart package (NO Flutter, ~34 files)
│ ├── lib/src/
│ │ ├── api/ # REST API client
│ │ ├── application/ # AG-UI application facade
│ │ ├── auth/ # OIDC discovery, token refresh
│ │ ├── domain/ # Data models
│ │ ├── http/ # HTTP abstraction layer
│ │ ├── errors/ # Exception hierarchy
│ │ └── utils/ # Utilities
│ └── test/ # ~23 test files
│
├── packages/soliplex_client_native/ # Flutter package - Native HTTP (~8 files)
│ └── lib/src/
│ ├── platform/ # Platform-specific factory
│ └── clients/ # CupertinoHttpClient for iOS/macOS
│
├── test/ # Widget and unit tests (~42 files)
├── android/, ios/, macos/, web/ # Platform-specific code
└── pubspec.yaml
2. Architecture
2.1 Three-Layer Design
flowchart TD
A["UI Components<br/>(Chat, History, HttpInspector)"]
B["Core Frontend<br/>Providers | Navigation | AG-UI Processing"]
C["soliplex_client<br/>(Pure Dart package)"]
A --> B
B --> C
style A fill:#e1f5ff
style B fill:#fff4e1
style C fill:#e8f5e9
2.2 State Management: Riverpod
Provider Hierarchy:
flowchart TD
config["configProvider<br/>(StateProvider)"]
url["urlBuilderProvider"]
transport["httpTransportProvider"]
api["apiProvider"]
rooms["roomsProvider"]
threads["threadsProvider(roomId)"]
current["currentRoomIdProvider /<br/>currentThreadIdProvider"]
activeRun["activeRunNotifierProvider<br/>(Main streaming orchestration)"]
derived["Derived: canSendMessageProvider,<br/>allMessagesProvider, isStreamingProvider"]
config --> url
config --> transport
transport --> api
api --> rooms
api --> threads
rooms --> current
threads --> current
current --> activeRun
activeRun --> derived
style config fill:#e1f5ff
style api fill:#fff4e1
style activeRun fill:#ffe1f5
style derived fill:#e8f5e9
2.3 HTTP Layer Architecture
flowchart TD
api["SoliplexApi (REST client)<br/>Layer 3: Business Logic"]
transport["HttpTransport<br/>(JSON + Error Mapping)<br/>Layer 2: Transport"]
client["SoliplexHttpClient<br/>(Platform abstractions)<br/>Layer 1: Clients"]
dart["DartHttpClient (dart:http)"]
cupertino["CupertinoHttpClient (NSURLSession)"]
api --> transport
transport --> client
client --> dart
client --> cupertino
style api fill:#e1f5ff
style transport fill:#fff4e1
style client fill:#ffe1f5
style dart fill:#e8f5e9
style cupertino fill:#e8f5e9
2.4 Navigation: GoRouter
| Route | Screen | Description |
|---|---|---|
/ |
HomeScreen | Backend URL configuration |
/login |
LoginScreen | OIDC provider selection |
/auth/callback |
AuthCallbackScreen | OAuth callback handler |
/rooms |
RoomsScreen | List all rooms |
/rooms/:roomId |
RoomScreen | Room view with thread selection |
/rooms/:roomId/thread/:threadId |
(redirect) | Redirects to /rooms/:roomId?thread=:threadId |
/settings |
SettingsScreen | App config and auth status |
Responsive Layout:
- Desktop (≥600px): Sidebar history panel + chat panel side-by-side
- Mobile (<600px): Chat panel only
3. Key Components
3.1 Data Models
ChatMessage:
- id: String
- user: ChatUser (user | assistant | system)
- type: MessageType (text | error | toolCall | genUi | loading)
- text: String?
- isStreaming: bool
- thinkingText: String?
- toolCalls: List<ToolCallInfo>?
- errorMessage: String?
- createdAt: DateTime
ActiveRunState (sealed class hierarchy):
sealed class ActiveRunState {
Conversation get conversation;
StreamingState get streaming;
List<ChatMessage> get messages;
bool get isRunning;
}
class IdleState extends ActiveRunState { } // No active run
class RunningState extends ActiveRunState { // Run executing
String get threadId;
String get runId;
bool get isStreaming;
}
class CompletedState extends ActiveRunState { // Run finished
CompletionResult result; // Success | FailedResult | CancelledResult
}
3.2 AG-UI Protocol
Event Types (sealed class hierarchy):
- Run lifecycle:
RunStartedEvent,RunFinishedEvent,RunErrorEvent - Message streaming:
TextMessageStartEvent,TextMessageContentEvent,TextMessageEndEvent - Tool calls:
ToolCallStartEvent,ToolCallArgsEvent,ToolCallEndEvent,ToolCallResultEvent - State:
StateSnapshotEvent,StateDeltaEvent - Activity:
ActivitySnapshotEvent,ActivityDeltaEvent - Messages:
MessagesSnapshotEvent - Custom:
CustomEvent,UnknownEvent
Streaming Pipeline:
flowchart LR
A[SSE Stream] --> B[Thread.run]
B --> C[Event parsing]
C --> D[Buffers]
D --> E[ActiveRunNotifier]
E --> F[UI]
style A fill:#e1f5ff
style F fill:#e8f5e9
3.3 Chat Flow
flowchart TD
A[User types message]
B[ChatInput.onSend text]
C[ChatPanel._handleSend]
D[Create thread if needed<br/>api.createThread]
E[activeRunNotifier.startRun<br/>roomId, threadId, userMessage]
F[Creates Thread]
G[Subscribes to eventStream]
H[Updates ActiveRunState]
I[MessageList watches<br/>allMessagesProvider]
J[Merges history + run messages]
K[Auto-scrolls to bottom]
A --> B
B --> C
C --> D
C --> E
E --> F
E --> G
E --> H
H --> I
I --> J
I --> K
style A fill:#e1f5ff
style E fill:#ffe1f5
style I fill:#fff4e1
style K fill:#e8f5e9
4. soliplex_client Package
Pure Dart - no Flutter dependency. Reusable on web, server, or desktop.
Implemented Components:
- Models & errors
- HTTP adapter interface + DartHttpAdapter
- HttpObserver + ObservableHttpAdapter
- HttpTransport, UrlBuilder, CancelToken
- API layer (SoliplexApi)
- AG-UI protocol (Thread, buffers, tool registry)
Test Coverage: ~600 tests, near 100% coverage
5. UI Components
Screens
| Screen | Purpose |
|---|---|
| HomeScreen | Backend URL configuration |
| LoginScreen | OIDC provider selection |
| AuthCallbackScreen | OAuth callback handler |
| RoomsScreen | List rooms from API |
| RoomScreen | Room view with thread selection |
| SettingsScreen | App config and auth status |
| BackendVersionsScreen | Backend version information |
| QuizScreen | Quiz feature |
Panels
| Panel | Purpose |
|---|---|
| ChatPanel | Message list + input, send/cancel/error handling |
| HistoryPanel | Thread list, new conversation, auto-selection |
| HttpInspectorPanel | HTTP traffic debugging with request grouping |
Shared Widgets
AppShell: Main scaffold with AppBar/SidebarAsyncValueHandler: Wraps AsyncValue with error handlingErrorDisplay: Exception-aware error UI with retryLoadingIndicator: Spinner with optional messageEmptyState: Icon + message for empty lists
6. Testing
Test Coverage:
- Frontend: ~42 test files covering auth, providers, features, widgets
- soliplex_client: ~23 test files
- Zero analyzer issues
Test Structure:
test/
├── core/
│ ├── auth/ # Auth layer tests (9 files)
│ ├── models/ # Model tests
│ └── providers/ # Provider tests (7 files)
├── features/ # Screen and widget tests
│ ├── auth/
│ ├── chat/
│ ├── history/
│ ├── home/
│ ├── inspector/
│ ├── login/
│ ├── room/
│ ├── rooms/
│ └── settings/
├── shared/ # Shared widget tests
└── helpers/ # Mocks and utilities
Key Utilities:
MockSoliplexApi: Mock API for testingMockActiveRunNotifier: Mock notifier with initial statecreateTestApp(): Helper to create testable app
7. Code Quality
Analyzer: Zero tolerance - no errors, warnings, or hints
Linting:
very_good_analysis(strict rules)dart format lib testbefore commitsmarkdownlint-clifor markdown
Conventions:
- PascalCase: Classes, enums, types
- camelCase: Variables, functions
_privateMethod: Private members prefixed
8. Notable Patterns
Sealed Classes for Events
sealed class AgUiEvent { ... }
final class RunStartedEvent extends AgUiEvent { ... }
// Enables exhaustive pattern matching
Builder Pattern for Models
Observer Pattern for HTTP
ObservableHttpAdapter wraps adapters for request inspection/logging.
Cancel Token
Graceful SSE stream cancellation via Completer pattern.
Responsive Breakpoint
600px mobile/desktop boundary in ThreadScreen.
9. Dependencies
Frontend App:
flutter_riverpod: ^3.1.0 # State management
go_router: ^17.0.0 # Navigation
flutter_appauth: ^11.0.0 # OIDC flows
flutter_secure_storage: ^10.0.0 # Secure token storage
shared_preferences: ^2.5.4 # Config persistence
package_info_plus: ^9.0.0 # App version info
http: ^1.2.0 # HTTP client
flutter_markdown: ^0.7.4+1 # Message rendering
flutter_highlight: ^0.7.0 # Code highlighting
intl: ^0.20.1 # Localization
meta: ^1.15.0 # Annotations
soliplex_client: path # Pure Dart client
soliplex_client_native: path # Native adapters
soliplex_client:
soliplex_client_native:
10. Key Architectural Decisions
- Pure Dart client package - Reusable across platforms without Flutter dependency
- Sealed classes for state - Type-safe exhaustive pattern matching (ActiveRunState, AuthState, CompletionResult)
- 3-layer HTTP abstraction - Testable adapters, transport, and API layers
- Platform-optimized adapters - NSURLSession on iOS/macOS for better performance
- Platform-specific auth - Native Keychain/SecureStorage vs Web localStorage
- Manual Riverpod providers - Explicit control over provider lifecycle
- Responsive dual-panel layout - Desktop sidebar with mobile fallback
11. Summary
This is a well-architected, production-quality Flutter frontend featuring:
- ✅ Clean 3-layer HTTP abstraction with platform adapters
- ✅ Pure Dart client package reusable across platforms
- ✅ Sophisticated AG-UI event streaming protocol
- ✅ Responsive dual-panel desktop + mobile chat
- ✅ OIDC authentication with platform-specific flows
- ✅ HTTP traffic inspector for debugging
- ✅ Comprehensive error handling with exception hierarchy
- ✅ Strict code quality (zero analyzer issues)
- ✅ Riverpod state management with clear provider hierarchy
- ✅ Sealed classes for type-safe state handling
- ✅ Platform-optimized native HTTP adapters