Skip to main content
Xolo is built around a strict separation of concerns: each layer has a single responsibility, depends only on the layers below it, and exposes a well-defined contract. This boundary discipline makes every module independently testable, keeps the UI free of database types, and lets the data implementation be swapped without touching a single widget. The application boots from a single ProviderScope in main.dart, and every dependency — database, HTTP client, auth services, navigation — flows through Riverpod providers.

The Four Layers

The Core layer provides infrastructure that every other layer can use without depending on Flutter’s widget tree. It never imports from domain, data, or presentation.Router — app_router.dartNavigation is handled by go_router (^15.1.2). The appRouter instance is a GoRouter that wraps all main routes inside a ShellRoute backed by HomeShell. AppRoutes is an abstract final class of typed path constants:
Helper functions (routeForTabIndex, tabIndexForRoute, railIndexForRoute, routeForRailIndex) translate between numeric navigation-rail/bottom-nav indices and route paths, keeping navigation logic out of widgets entirely.Theme — XoloPremiumTheme & XoloDesignTokensXoloPremiumTheme exposes darkTheme(int) and lightTheme(int) factory methods that return fully configured ThemeData objects using Material 3. Both themes set Inter as the body font and JetBrains Mono for code/URL fields via google_fonts. The dark theme uses XoloPalette.black (#000000) as the scaffold background; the light theme uses XoloPalette.lightBg (#FAFAFA).XoloDesignTokens (xolo_design_tokens.dart) centralises every visual constant:
  • XoloSpacing — xs (4), sm (8), md (12), lg (16), xl (24), xxl (32)
  • XoloRadius — sm (8 px), md (12 px), lg (16 px) as both double values and pre-built BorderRadius instances
  • XoloPalette — named colour constants for both dark (base, raised, hover, line, text, accent) and light (lightBg, lightSurface, lightLine) surfaces
  • XoloMotion — fast (120 ms) and normal (200 ms) animation durations
  • XoloLayout — railWidth (72), urlBarHeight (56), sectionTabHeight (48), requestTabHeight (40)
  • XoloSurfaces — panel() and card() factory methods that return BoxDecoration instances consistent with the active ColorScheme
  • XoloTypography — typed TextStyle factories: sectionLabel, cardTitle, cardSubtitle, meta
  • XoloA11y — minTouchTarget (44) for WCAG-compliant tap targets
Network — HttpClientProvider & RequestPipelinedioProvider creates a Dio instance configured with 15 s connect, 30 s receive, and 30 s send timeouts. An InterceptorsWrapper logs every request and response through AppLogger. The error handler applies an automatic retry strategy: idempotent methods (GET, HEAD, OPTIONS) are retried up to twice on 429/5xx responses and on transient connection errors, with a back-off of 300 ms × (attempt + 1).RequestPipeline is a plain Dart class (registered as requestPipelineProvider) that encapsulates the full HTTP execution path shared by the Composer screen and CollectionRunnerService. It resolves {{variables}} in URLs, headers, and bodies via VariableParser, resolves auth inheritance via AuthResolverService, refreshes OAuth 2.0 tokens when needed, and injects Authorization headers for bearer, oauth2, basic, and api_key auth types. It returns a RequestOutput value object with statusCode, durationMs, resolvedUrl, data, error, and cancelled fields.ServicesConfig — AppConfig & SecureStorageAppConfig is an immutable value class holding schemaVersion, themeModeDefault, allowAbsoluteUrl, and a featureFlags map. It is loaded by appConfigProvider (FutureProvider) from two settings keys: app_config_runtime (server-pushed overrides) and app_config_user_override (local user preferences), merged over compiled defaults. Sensitive credentials are stored separately in flutter_secure_storage.

State Management

Xolo uses flutter_riverpod ^3.1.0. The entire app is wrapped in a single ProviderScope at the root of main(). Provider types in use: xoloRepositoryProvider is the single entry point for all persistent data access in the presentation layer. Every StreamProvider that watches a database collection calls ref.watch(xoloRepositoryProvider) first.
Navigation is driven by go_router. All routes are nested inside a ShellRoute that renders HomeShell, which provides the adaptive navigation shell (bottom navigation bar on phones, navigation rail on tablets/desktop).
All pageBuilder callbacks return NoTransitionPage to eliminate route transition animations, keeping navigation feel instant.

Tech Stack


Explore Further

Data Layer

Deep-dive into the Drift schema, DriftXoloRepository, entity mappers, migrations, and reactive query patterns.

Domain Layer

Explore XoloRepository’s full method contract, every domain entity, and the pure testable services that orchestrate collection runs and assertion evaluation.