Skip to content

Mobile Shared Packages

All three mobile apps (BoMobileApp, ERPMobileApps, VanSalesMobileApp) share three Git submodule packages. This page covers what each package provides, how to add new functionality to them, and Melos commands for managing updates.


Package Overview

PackageGit Submodule PathPurpose
MobileDesignSystemMobileDesignSystem/UI component library — tokens, widgets, themes
MobileAPIClientsMobileAPIClients/Auto-generated Dart API clients (OpenAPI codegen)
MobileSharedCompMobileSharedComp/Auth utilities, base classes, sync helpers, constants

Each package is a Git submodule that is included in every app's melos.yaml as a local package dependency.


MobileDesignSystem

The design system package provides a consistent look and feel across all three apps. It is the only place where colours, typography, spacing, and reusable widgets are defined.

Contents

CategoryExamples
TokensMicrotecColors, MicrotecTypography, MicrotecSpacing, MicrotecBorderRadius
ThemeMicrotecTheme.light(), MicrotecTheme.dark()ThemeData instances
Layout widgetsMicrotecScaffold, MicrotecAppBar, MicrotecBottomNav, MicrotecDrawer
Form widgetsMicrotecTextField, MicrotecDropdown, MicrotecDatePicker, MicrotecSearchField
Data displayMicrotecCard, MicrotecDataTable, MicrotecListTile, MicrotecStatusBadge
FeedbackMicrotecLoadingOverlay, MicrotecSnackbar, MicrotecDialog, MicrotecBottomSheet
ButtonsMicrotecButton (primary/secondary/outlined/text), MicrotecIconButton
PDF helpersMicrotecPdfPage, MicrotecPdfTable — layout helpers for pdf package

Structure

MobileDesignSystem/
├── lib/
│   ├── src/
│   │   ├── tokens/         # Colors, typography, spacing, radii
│   │   ├── theme/          # ThemeData configuration
│   │   ├── widgets/        # Reusable Flutter widgets
│   │   └── pdf/            # PDF layout utilities
│   └── microtec_design_system.dart  # Public barrel export
├── test/
└── pubspec.yaml

Adding a new component

  1. Create the widget file in lib/src/widgets/<category>/<widget_name>.dart.
  2. Export it from the barrel file: lib/microtec_design_system.dart.
  3. Write a widget test in test/.
  4. Update the package version in pubspec.yaml (semver).
  5. Commit to the MobileDesignSystem repo.
  6. In each app that needs the update, run melos run get to pull the new version.

Design tokens belong here, not in app code

Never define colours, font sizes, or spacing values directly in app code. Always reference tokens from MicrotecColors, MicrotecTypography, or MicrotecSpacing. This ensures visual consistency and makes theme changes a single-point update.


MobileAPIClients

The API clients package contains Dart classes auto-generated from the backend's OpenAPI (Swagger) specifications. Apps never write raw HTTP requests — they always use these generated clients.

Contents

Client classBackend service
BusinessOwnersApiClientBusinessOwners.Apis
AppsPortalApiClientAppsPortal.Apis
HrApiClientHR.Apis
InventoryApiClientInventory.Apis
AttachmentApiClientAttachment.Apis
NotificationApiClientNotification.Apis

Structure

MobileAPIClients/
├── lib/
│   ├── src/
│   │   ├── business_owners/    # Generated models + client
│   │   ├── apps_portal/        # Generated models + client
│   │   ├── hr/
│   │   ├── inventory/
│   │   ├── attachment/
│   │   └── notification/
│   └── mobile_api_clients.dart
├── openapi/                    # OpenAPI spec files (source of truth)
│   ├── business_owners.yaml
│   ├── apps_portal.yaml
│   └── ...
├── scripts/
│   └── generate.sh             # Runs openapi-generator-cli
└── pubspec.yaml

How to regenerate clients after a backend change

When the backend team adds or modifies endpoints, the OpenAPI spec is updated and clients must be regenerated:

bash
cd MobileAPIClients

# Ensure openapi-generator-cli is installed
dart pub global activate openapi_generator_annotations

# Pull the latest OpenAPI spec from the backend's Swagger endpoint
curl https://gateway.microtecstage.com/swagger/apps-portal/swagger.json \
  -o openapi/apps_portal.yaml

# Regenerate the Dart client
./scripts/generate.sh apps_portal

# Review the generated diff
git diff lib/src/apps_portal/

After regeneration:

  1. Review the diff to ensure no breaking changes were introduced silently.
  2. Update the package version in pubspec.yaml.
  3. Commit and push to the MobileAPIClients repo.
  4. In each consuming app, run melos run get to pick up the new version.

Never hand-edit generated files

Files in lib/src/<service>/ are fully auto-generated. Any manual edits will be overwritten on the next generate.sh run. Put customisations in thin wrapper classes in the app's own data/api/ layer.

Using a client in app code

dart
// data/api/invoice_api.dart (app code — wrapper over generated client)
import 'package:mobile_api_clients/mobile_api_clients.dart';

class InvoiceApi {
  final AppsPortalApiClient _client;

  InvoiceApi(this._client);

  Future<List<Invoice>> getAllInvoices({int page = 1, int pageSize = 20}) async {
    final response = await _client.invoicesGet(page: page, pageSize: pageSize);
    return response.data ?? [];
  }

  Future<Invoice> getInvoiceById(int id) async {
    return await _client.invoicesIdGet(id: id);
  }
}

MobileSharedComp

The shared component library provides non-UI utilities that are common across all apps: authentication, storage, base classes, and sync infrastructure.

Contents

CategoryExamples
AuthMicrotecAuthService — Keycloak PKCE flow using flutter_appauth, token storage, refresh
StorageSecureTokenStorage — flutter_secure_storage wrapper; AppPreferences — shared_preferences wrapper
Base classesBaseScreen (StatefulWidget with standard lifecycle), BaseBloc, BaseRepository
SyncSyncManager, SyncQueue, ConnectivityWatcher — offline sync infrastructure
NetworkMicrotecHttpClient — Dio instance pre-configured with the auth interceptor and base URL
UtilitiesDateFormatter, CurrencyFormatter, PhoneNumberUtils, ValidationUtils
ConstantsApiPaths, StorageKeys, AppConstants
ExceptionsApiException, NetworkException, AuthException — typed error hierarchy

Structure

MobileSharedComp/
├── lib/
│   ├── src/
│   │   ├── auth/           # MicrotecAuthService, KeycloakConfig
│   │   ├── storage/        # SecureTokenStorage, AppPreferences
│   │   ├── network/        # MicrotecHttpClient, auth interceptor
│   │   ├── sync/           # SyncManager, SyncQueue, ConnectivityWatcher
│   │   ├── base/           # BaseScreen, BaseBloc, BaseRepository
│   │   ├── utils/          # Date, currency, phone, validation utilities
│   │   ├── constants/      # ApiPaths, StorageKeys, AppConstants
│   │   └── exceptions/     # Typed exception classes
│   └── microtec_shared.dart
├── test/
└── pubspec.yaml

Using auth in app code

dart
import 'package:microtec_shared/microtec_shared.dart';

// DI registration (in core/di/injection.dart)
getIt.registerSingleton<MicrotecAuthService>(
  MicrotecAuthService(
    config: KeycloakConfig(
      url: Environment.keycloakUrl,
      realm: Environment.realm,
      clientId: 'mobile-erp',
      redirectUri: 'com.microtec.erp://callback',
    ),
  ),
);

// Usage in a Bloc
class AuthBloc extends BaseBloc<AuthEvent, AuthState> {
  final MicrotecAuthService _auth;

  AuthBloc(this._auth) : super(AuthInitial()) {
    on<LoginRequested>(_onLogin);
  }

  Future<void> _onLogin(LoginRequested event, Emitter<AuthState> emit) async {
    try {
      emit(AuthLoading());
      await _auth.login();
      emit(AuthAuthenticated(claims: _auth.getClaims()));
    } on AuthException catch (e) {
      emit(AuthFailure(message: e.message));
    }
  }
}

Adding a new shared utility

  1. Add the class to the appropriate subfolder in lib/src/.
  2. Export from the barrel: lib/microtec_shared.dart.
  3. Write unit tests in test/.
  4. Update the version in pubspec.yaml.
  5. Commit to the MobileSharedComp repo.
  6. Run melos run get in consuming apps.

Melos Commands for Package Management

Run these from inside any app directory (BoMobileApp/, ERPMobileApps/, or VanSalesMobileApp/):

bash
# Bootstrap all packages including submodules — run after cloning or pulling new submodule versions
melos run init

# Install / update all package dependencies
melos run get

# Run tests across all packages
melos run test

# Run the app
melos run run

# Build Android APK
melos run build-apk

Updating a submodule to a new commit

bash
# From the app root
cd MobileDesignSystem
git pull origin main
cd ..
git add MobileDesignSystem
git commit -m "chore: update MobileDesignSystem to latest"

# Then re-bootstrap
melos run init

Checking submodule status

bash
git submodule status

A + prefix means the submodule is ahead of the pinned commit — commit the update or reset.

Submodule pinning

Each app pins the shared packages to a specific commit SHA. This ensures that a change in MobileDesignSystem does not automatically break VanSalesMobileApp — each app opts in to updates explicitly by bumping the submodule pointer.

Internal Documentation — Microtec Platform Team