API Dash Architecture Overview

February 7, 2026 · View on GitHub

This document provides an overview of the API Dash project architecture for developers and contributors.

Technology Stack

ComponentTechnology
FrameworkFlutter (Dart)
State ManagementRiverpod
Local StorageHive (NoSQL embedded database)
Code Generation (models)Freezed, json_serializable, build_runner
Code Generation (API)Jinja templates
Monorepo ManagementMelos
PlatformsmacOS, Windows, Linux, iOS, Android, Web

Project Structure

apidash/
├── lib/                          # Main application code
│   ├── main.dart                 # Entry point
│   ├── app.dart                  # App widget & window lifecycle
│   ├── consts.dart               # Constants, enums, defaults
│   ├── codegen/                  # Code generation for 30+ languages
│   ├── dashbot/                  # AI assistant (Dashbot)
│   ├── importer/                 # Import from cURL, Postman, etc.
│   ├── models/                   # Data models (Freezed)
│   ├── providers/                # Riverpod state management
│   ├── screens/                  # UI screens and pages
│   ├── services/                 # Business logic & persistence
│   ├── utils/                    # Utility functions
│   └── widgets/                  # Reusable UI components
├── packages/                     # Shared packages (monorepo)
│   ├── apidash_core/             # Core business logic
│   ├── apidash_design_system/    # Design tokens & UI components
│   ├── curl_parser/              # cURL command parser
│   ├── postman/                  # Postman collection parser
│   ├── insomnia_collection/      # Insomnia file parser
│   ├── har/                      # HAR file parser
│   ├── genai/                    # AI provider integration
│   ├── json_explorer/            # JSON viewer widget
│   ├── json_field_editor/        # JSON field editor widget
│   ├── better_networking/        # Enhanced HTTP client
│   ├── multi_trigger_autocomplete_plus/  # Autocomplete widget
│   └── seed/                     # Seed/utility package
├── test/                         # Unit & widget tests
├── integration_test/             # Integration tests
└── doc/                          # Documentation

Application Initialization

The app starts in lib/main.dart and follows this initialization sequence:

  1. Analytics setup — Initialize telemetry (Stac).
  2. AI model loading — Load available AI models via ModelManager.
  3. Settings loading — Read user preferences from SharedPreferences.
  4. Hive initialization — Open persistent storage boxes for requests, environments, history, and Dashbot data.
  5. Window configuration — Restore window size and position on desktop platforms.
  6. Provider injection — Wrap the app in Riverpod ProviderScope with initial settings.
  7. Run app — Launch DashApp.

Widget Hierarchy

DashApp (ConsumerWidget)
  └── MaterialApp
      └── App (ConsumerStatefulWidget — manages window lifecycle)
          └── Dashboard (Desktop) or MobileDashboard (Mobile)
              ├── Navigation Rail (left sidebar)
              │   ├── Requests tab     → HomePage
              │   ├── Variables tab    → EnvironmentPage
              │   ├── History tab      → HistoryPage
              │   └── Logs tab         → TerminalPage
              └── Content Area
                  └── HomePage
                      └── DashboardSplitView (resizable)
                          ├── CollectionPane (request list)
                          └── RequestEditorPane (request editor + response)

State Management (Riverpod)

All application state is managed through Riverpod providers. Providers are organized by domain:

Provider Files

FilePurpose
collection_providers.dartRequest collection CRUD, selection, ordering
ui_providers.dartUI state (navigation, edit mode, search, visibility)
settings_providers.dartTheme, window, codegen language, SSL, workspace
environment_providers.dartEnvironment variables and active environment
history_providers.dartRequest history management
ai_providers.dartAI/Dashbot integration
terminal_providers.dartDebug console and network logs

Key Providers

// Currently selected request
final selectedIdStateProvider = StateProvider<String?>((ref) => null);

// Collection of all requests (Map<String, RequestModel>)
final collectionStateNotifierProvider = StateNotifierProvider<CollectionStateNotifier, Map<String, RequestModel>?>(...)

// Request ordering
final requestSequenceProvider = StateProvider<List<String>>((ref) => []);

// App settings (theme, workspace, etc.)
final settingsProvider = StateNotifierProvider<ThemeStateNotifier, SettingsModel>(...)

// Navigation
final navRailIndexStateProvider = StateProvider<int>((ref) => 0);

Data Flow Example

User clicks Send →
  collectionStateNotifierProvider sends HTTP request →
    Response stored in RequestModel →
      selectedRequestModelProvider reactively updates →
        Response pane UI rebuilds with new data

Data Models

Models are defined using Freezed for immutability and json_serializable for JSON conversion.

ModelFilePurpose
RequestModellib/models/request_model.dartFull request with URL, headers, body, auth, scripts, and cached response
HistoryRequestModellib/models/history_request_model.dartSnapshot of a sent request for history
HistoryMetaModellib/models/history_meta_model.dartMetadata for history entries (timestamp, status)
SettingsModellib/models/settings_model.dartApp preferences (theme, window, defaults)

The core HTTP request/response models (HttpRequestModel, HttpResponseModel) are defined in the apidash_core package.

Persistent Storage (Hive)

API Dash uses Hive, a lightweight NoSQL database optimized for Flutter.

Storage Boxes

Box NameTypeContent
apidash-dataNormalRequest models (full request data)
apidash-environmentsNormalEnvironment variable sets
apidash-history-metaNormalHistory metadata (dates, status codes)
apidash-history-lazyLazyFull history request data (loaded on demand)
apidash-dashbot-dataLazyDashbot AI conversation data

HiveHandler API

The HiveHandler class in lib/services/hive_services.dart provides all data access:

class HiveHandler {
  // Request CRUD
  dynamic getIds();
  void setIds(List<String> ids);
  dynamic getRequestModel(String id);
  void setRequestModel(String id, Map<String, dynamic> data);
  void removeRequestModel(String id);

  // Environment CRUD
  dynamic getEnvironmentIds();
  dynamic getEnvironment(String id);

  // History (lazy-loaded)
  dynamic getHistoryIds();
  dynamic getHistoryMeta(String id);
  dynamic getHistoryRequest(String id);
}

Data Location

  • Desktop: User-selected workspace folder.
  • Mobile: App documents directory (managed by OS).
  • Web: Browser localStorage (via apidash_core).

Code Generation System

The code generation module at lib/codegen/ converts request configurations into runnable code. See Adding a New Code Generator for instructions on extending this system.

Architecture

Codegen class (lib/codegen/codegen.dart)
  ├── getCode(CodegenLanguage, HttpRequestModel) → String
  └── Switch on language enum → delegate to language-specific class
      ├── PythonRequests (lib/codegen/python/requests.dart)
      ├── DartHttpCodeGen (lib/codegen/dart/http.dart)
      ├── ... (30+ implementations)
      └── Each class uses Jinja templates for code output

Template Pattern

Each language generator uses Jinja templates (via package:jinja) with conditional blocks:

final String kTemplateStart = """import requests
{% if hasFormData %}from requests_toolbelt import MultipartEncoder
{% endif %}
url = '{{url}}'
""";

Import System

The import module at lib/importer/ supports Postman, cURL, Insomnia, and HAR formats. Parsing is delegated to dedicated packages under packages/:

User selects file → Import dialog →
  Importer.getHttpRequestModelList(format, content) →
    Format-specific parser (curl_parser, postman, insomnia_collection, har) →
      List<HttpRequestModel> →
        Added to collection via CollectionStateNotifier

Packages Overview

The monorepo contains reusable packages managed by Melos:

PackagePurpose
apidash_coreCore models, HTTP client, utilities shared across the app
apidash_design_systemMaterial 3 design tokens, reusable UI components
curl_parserParse cURL commands into request models
postmanParse Postman Collection v2.1 files
insomnia_collectionParse Insomnia v4 exports
harParse HTTP Archive v1.2 files
genaiAI provider integration (model management, API calls)
better_networkingEnhanced HTTP client with interceptors
json_explorerInteractive JSON viewer widget
json_field_editorJSON field editor widget
multi_trigger_autocomplete_plusMulti-trigger autocomplete for env variables
seedSeed utilities

Desktop vs. Mobile

API Dash adapts its layout based on screen size:

if (context.isMediumWindow) {
  // Mobile layout — stacked tabs, touch-friendly
} else {
  // Desktop layout — split panes, keyboard shortcuts
}

Key differences:

  • Desktop: Resizable split pane with collection sidebar and editor side-by-side. Drag handles for reordering.
  • Mobile: Tab-based navigation with full-screen views. Long-press for drag-to-reorder with a delay for scroll disambiguation.

Key Patterns

UUID Generation

All requests, environments, and history entries use UUIDs as identifiers:

final id = getNewUuid(); // From lib/utils/utils.dart

Immutable State Updates

Riverpod state is always replaced, never mutated:

// Correct: create a new map
state = {...state!, id: updatedModel};

// Incorrect: mutating in place
// state![id] = updatedModel;

Platform Checks

// From lib/consts.dart
final kIsWindows = !kIsWeb && Platform.isWindows;
final kIsMacOS = !kIsWeb && Platform.isMacOS;
final kIsLinux = !kIsWeb && Platform.isLinux;
final kIsMobile = !kIsWeb && (Platform.isAndroid || Platform.isIOS);
final kIsDesktop = !kIsWeb && (kIsWindows || kIsMacOS || kIsLinux);

Further Reading