Files
stadtbote-app/AGENTS.md
T
2026-02-12 09:13:40 +01:00

15 KiB

Stadtbote - Project Documentation for AI Agents

Project Overview

Stadtbote is a Flutter-based mobile application for courier and delivery services. The app is designed for drivers to manage delivery jobs, track their location, communicate with dispatchers, and handle delivery confirmations including signatures and photos.

The application is primarily in German and targets the German logistics market ("Stadtbote" translates to "City Messenger").

Key Features

  • Real-time job assignment and management (assigned, accepted, finished states)
  • GPS location tracking and transmission to backend
  • Interactive maps for navigation and job visualization
  • Chat/messaging system with dispatchers
  • Digital signature capture for delivery confirmation
  • Photo capture for delivery documentation
  • PDF document viewing
  • Audio notifications for new jobs and messages

Technology Stack

Core Framework

  • Flutter 3.x (Dart SDK >=3.9.0 <4.0.0)
  • Dart programming language

State Management & Data Persistence

  • ObjectBox (v4.0.3) - Local NoSQL database for offline data persistence
  • SharedPreferences - For user preferences and app settings
  • dart_mq - Internal message bus for component communication
  • shared_map - Thread-safe shared memory for job state management

Network & Communication

  • mqtt5_client (v4.4.0) - MQTT protocol for real-time server communication
  • http (v1.3.0) - HTTP client for bootstrap and REST API calls
  • GZip compression - All MQTT payloads are compressed

Location & Maps

  • geolocator (v13.0.2) - GPS location services
  • flutter_map (v8.1.0) - OpenStreetMap integration
  • flutter_osm_plugin (v1.3.6) - Alternative OSM plugin
  • latlong2 (v0.9.1) - Geographic coordinate calculations

UI Components

  • flutter_chat_ui (v1.6.10) - Chat interface
  • flutter_chat_types (v3.6.2) - Chat message types
  • carousel_slider (v5.0.0) - Image carousels
  • signature (v6.0.0) - Digital signature capture
  • expandable (v5.0.1) - Collapsible UI sections
  • badges (v3.1.1) - Notification badges
  • animated_toggle_switch (v0.8.4) - Toggle switches

Media & Files

  • image_picker (v1.1.2) - Camera integration for photos
  • audioplayers (v6.2.0) - Audio notifications
  • pdfrx (v2.2.20) - PDF document viewer
  • image (v4.2.0) - Image processing
  • archive (v4.0.3) - File compression utilities
  • path_provider (v2.1.2) - File system access

Utilities

  • uuid (v4.5.1) - Unique identifier generation
  • mime (v2.0.0) - MIME type handling
  • intl (v0.20.2) - Internationalization
  • synchronized (v3.1.0) - Thread synchronization
  • permission_handler (v11.4.0) - Runtime permission management
  • url_launcher (v6.2.4) - External URL handling
  • device_info_plus (v11.3.2) - Device information
  • package_info_plus (v8.0.2) - App version information

Code Generation

  • build_runner (v2.4.13) - Code generation runner
  • json_serializable (v6.6.2) - JSON serialization code generation
  • objectbox_generator (v4.0.3) - ObjectBox model generation

Project Structure

lib/
├── main.dart                    # Application entry point
├── objectbox.g.dart            # Generated ObjectBox code (DO NOT EDIT)
│
├── content_views/              # Main UI pages/screens
│   ├── main_page.dart          # Main dashboard with menu buttons
│   ├── assigned_jobs_page.dart # List of assigned/pending jobs
│   ├── accepted_jobs_page.dart # List of accepted jobs
│   ├── finished_jobs_page.dart # Job history
│   ├── messages_page.dart      # Chat/messaging interface
│   ├── tour_details_page.dart  # Tour/job detail view
│   ├── tour_list_page.dart     # List of tours
│   ├── task_list_page.dart     # Individual tasks within tours
│   ├── approach_area_page.dart # Map showing approach area
│   ├── set_desired_zip_page.dart # Set preferred postal code
│   ├── pdf_viewer_page.dart    # PDF document viewer
│   └── utils/                  # Content view utilities
│       ├── content_view_widget.dart  # Base class for content views
│       └── widget_stack.dart         # Navigation stack management
│
├── model/                      # Data models (ObjectBox entities)
│   ├── job.dart               # Delivery job entity
│   ├── job_tour.dart          # Tour within a job
│   ├── tour_task.dart         # Individual task in a tour
│   ├── tour_position.dart     # Geographic position
│   ├── task_info.dart         # Task information
│   ├── session_status.dart    # Current session/user status
│   ├── status.dart            # General status
│   ├── location_status.dart   # Location/zip code status
│   ├── chat_message.dart      # Chat message entity
│   ├── rank.dart              # User ranking
│   ├── log_entry.dart         # App log entries
│   ├── pictures.dart          # Photo attachments
│   └── enqueued_message.dart  # Pending MQTT messages
│
├── network_messages/          # JSON DTOs for network communication
│   ├── *.dart                # Message classes
│   └── *.g.dart              # Generated serialization code
│
├── popups/                    # Dialog and popup widgets
│   ├── accept_jobs_popup.dart
│   ├── infos_popup.dart
│   ├── map_popup.dart
│   └── tasks_popups/          # Task-specific popups
│       ├── arrived_popup.dart
│       ├── signature_popup.dart
│       ├── take_photos_popup.dart
│       └── ...
│
├── tools/                     # Core utilities and services
│   ├── constants.dart         # App constants, message topics
│   ├── util.dart              # Utility functions
│   ├── mqtt_core.dart         # MQTT client implementation
│   ├── connection_status.dart # Connection state management
│   ├── page_base.dart         # Base page class
│   ├── colored_safe_area.dart # UI component
│   ├── pdf_service.dart       # PDF handling
│   ├── extended_stateful_builder.dart
│   ├── message_header.dart    # Message envelope structure
│   └── messages/              # Internal message classes
│       ├── bwv_message.dart
│       ├── connect_client_message.dart
│       ├── job_received_message.dart
│       └── ...
│
└── messages/                  # App-level message definitions
    └── pop_content_view_message.dart

assets/                        # Static resources
├── *.png                     # Icons and images
├── sounds/                   # Audio files (MP3)
│   ├── aaa.mp3
│   ├── asbeep.mp3
│   └── job_received.mp3
└── json/                     # Static JSON files
    └── bootstrap_response.json

Architecture Overview

Message-Driven Architecture

The application uses a message-driven architecture with dart_mq as the internal message bus for decoupled component communication:

  • Components subscribe to named message queues (topics)
  • Messages are strongly typed and passed between UI, services, and data layers
  • Key message topics are defined in lib/tools/constants.dart

Data Flow

MQTT Server <-> MqttCore (mqtt_core.dart) <-> Message Bus <-> UI Components
                   |
                   v
            ObjectBox Database
                   |
                   v
           SharedPreferences

Key Components

  1. MqttCore (lib/tools/mqtt_core.dart)

    • Manages MQTT connection to backend (bootstrap.assecutor.de)
    • Handles message encoding/decoding with GZip compression
    • Implements automatic reconnection with exponential backoff
    • Manages message queueing for offline scenarios
    • Sends GPS tracking data every 120 seconds
  2. Main App Structure (lib/main.dart)

    • Initializes ObjectBox store
    • Sets up location tracking service
    • Configures message queues
    • Manages navigation stack with custom WidgetStack
  3. Content Views (lib/content_views/)

    • All pages extend ContentViewWidget
    • Each view provides a custom header via getHeaderWidget()
    • Navigation uses push/pop/replace operations via message bus
  4. Models (lib/model/)

    • All entities use ObjectBox annotations (@Entity, @Id, etc.)
    • Models support JSON serialization for network communication
    • externalId field used for server-side IDs, separate from ObjectBox id

Build Commands

Development

# Get dependencies
flutter pub get

# Run code generation (required after model changes)
dart run build_runner build

# Run in debug mode
flutter run

# Run on specific device
flutter run -d <device_id>

Build for Production

# Android APK
flutter build apk

# Android App Bundle
flutter build appbundle

# iOS
flutter build ios

# Web
flutter build web

Code Generation

The project uses build_runner for code generation. Run this after modifying:

  • ObjectBox entity classes (generates objectbox.g.dart)
  • JSON serializable network message classes (generates *.g.dart files)
dart run build_runner build

Code Style Guidelines

Linting

  • Uses flutter_lints v5.0.0 (included via analysis_options.yaml)
  • Standard Flutter linting rules apply
  • Specific lints can be disabled in analysis_options.yaml

Naming Conventions

  • Files: lowercase_with_underscores.dart
  • Classes: PascalCase
  • Methods/Variables: camelCase
  • Constants: camelCase for local, no strict convention for global
  • Private members: prefix with underscore _

Import Style

  • Use package imports for project files: package:stadtbote/...
  • Group imports: Flutter/Dart core, third-party, project files

Comments

  • Code comments are primarily in German
  • Use // for single-line comments
  • Use /* */ for multi-line comments

State Management Patterns

Job States

Jobs progress through three main states (defined in constants.dart):

  • stateAssigned = 0 - Job assigned but not yet accepted
  • stateAccepted = 1 - Job accepted by driver
  • stateFinished = 2 - Job completed
  • stateFinishedNotConfirmed = 9 - Finished but pending confirmation

Connection States

  • notConnected - Disconnected from MQTT broker
  • connected - Connected and ready

Location Tracking

  • Continuous GPS tracking when app is active
  • Location sent every 120 seconds via MQTT
  • Stored thread-safely using Lock from synchronized package

Testing

Note: The project currently has no automated tests. When adding tests:

# Run tests
flutter test

Recommended test structure (to be created):

test/
├── model/              # Model unit tests
├── network_messages/   # Serialization tests
├── tools/             # Utility tests
└── widget/            # Widget tests

Security Considerations

Network Security

  • MQTT connection uses authentication (username/password)
  • Will message configured for connection loss detection
  • All payloads are GZip compressed and UTF-8 encoded
  • Bootstrap endpoint: https://bootstrap.assecutor.de

Data Storage

  • ObjectBox database is local to device
  • SharedPreferences used for non-sensitive settings only
  • No sensitive data encryption currently implemented

Permissions

The app requires these permissions:

  • Location (GPS) - Continuous tracking during deliveries
  • Camera - Photo capture for delivery confirmation
  • Storage - Saving photos and PDFs
  • Internet - MQTT and HTTP communication

Device Identification

  • Each device generates a UUID stored in SharedPreferences
  • Device info (manufacturer, model, OS version) sent during bootstrap

Deployment

Android

  • Application ID: de.assecutor.stadtbote
  • Min SDK: 28 (Android 9.0)
  • Target/Compile SDK: 34-35
  • Signing configured via key.properties file (not in repo)
  • ProGuard disabled for release builds

iOS

  • Bundle identifier configured in Xcode project
  • Location background mode required
  • Camera permission required

Version Management

  • Version defined in pubspec.yaml (currently 347.0.0+347)
  • Build number increments with each release
  • Version display uses package_info_plus

Backend Integration

Bootstrap Process

  1. App sends device info to https://bootstrap.assecutor.de/bootstrap
  2. Server responds with MQTT broker details and topics
  3. App connects to MQTT broker with credentials
  4. Session initialized with start_session message

MQTT Topics

Topics are dynamically assigned during bootstrap:

  • fromServerTopic - Server-to-client messages
  • toServerTopic - Client-to-server messages

Message Types

Server handles these message types:

  • session - Session initialization/updates
  • status - Status updates
  • ranking - Driver rankings
  • job - Job assignments
  • job_del - Job deletions
  • sync_request - Data synchronization
  • location_status - Location-based status
  • mssg - Chat messages
  • track - GPS tracking data
  • logout - User logout

Common Development Tasks

Adding a New Model

  1. Create class in lib/model/ with @Entity() annotation
  2. Add @Id() field for ObjectBox ID
  3. Add fields with appropriate types
  4. Implement fromJson() and toJson() methods
  5. Run dart run build_runner build
  6. Import model in lib/objectbox.g.dart imports (auto-generated)

Adding a New Page

  1. Create file in lib/content_views/
  2. Extend ContentViewWidget
  3. Implement getHeaderWidget() method
  4. Add navigation message in appropriate place
  5. Add page to message subscription if needed

Adding MQTT Message Types

  1. Create class in lib/network_messages/
  2. Add part 'filename.g.dart'; directive
  3. Use @JsonSerializable() annotation
  4. Run code generation
  5. Add handling in MqttCore._setupMqtt() switch statement

Troubleshooting

Common Issues

Build fails with ObjectBox errors:

  • Run dart run build_runner build to regenerate models

MQTT connection issues:

  • Check bootstrap endpoint availability
  • Verify device has internet connection
  • Check that UUID is generated (first app launch)

Location not updating:

  • Verify location permissions granted
  • Check that location services are enabled on device

Missing generated files:

  • Run flutter pub get then dart run build_runner build

Language Notes

The application interface and all user-facing text is in German. When making changes:

  • Keep UI text in German
  • Keep code comments in German (following existing pattern)
  • Internal identifiers (class names, variables) use English
  • User-facing strings use German

Example German terms used in UI:

  • "Zugewiesene Aufträge" - Assigned Jobs
  • "Angenommene Aufträge" - Accepted Jobs
  • "Erledigte Aufträge" - Finished Jobs
  • "Abmelden" - Logout
  • "Zurück" - Back