Appearance
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
| Package | Git Submodule Path | Purpose |
|---|---|---|
MobileDesignSystem | MobileDesignSystem/ | UI component library — tokens, widgets, themes |
MobileAPIClients | MobileAPIClients/ | Auto-generated Dart API clients (OpenAPI codegen) |
MobileSharedComp | MobileSharedComp/ | 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
| Category | Examples |
|---|---|
| Tokens | MicrotecColors, MicrotecTypography, MicrotecSpacing, MicrotecBorderRadius |
| Theme | MicrotecTheme.light(), MicrotecTheme.dark() — ThemeData instances |
| Layout widgets | MicrotecScaffold, MicrotecAppBar, MicrotecBottomNav, MicrotecDrawer |
| Form widgets | MicrotecTextField, MicrotecDropdown, MicrotecDatePicker, MicrotecSearchField |
| Data display | MicrotecCard, MicrotecDataTable, MicrotecListTile, MicrotecStatusBadge |
| Feedback | MicrotecLoadingOverlay, MicrotecSnackbar, MicrotecDialog, MicrotecBottomSheet |
| Buttons | MicrotecButton (primary/secondary/outlined/text), MicrotecIconButton |
| PDF helpers | MicrotecPdfPage, 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.yamlAdding a new component
- Create the widget file in
lib/src/widgets/<category>/<widget_name>.dart. - Export it from the barrel file:
lib/microtec_design_system.dart. - Write a widget test in
test/. - Update the package version in
pubspec.yaml(semver). - Commit to the
MobileDesignSystemrepo. - In each app that needs the update, run
melos run getto 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 class | Backend service |
|---|---|
BusinessOwnersApiClient | BusinessOwners.Apis |
AppsPortalApiClient | AppsPortal.Apis |
HrApiClient | HR.Apis |
InventoryApiClient | Inventory.Apis |
AttachmentApiClient | Attachment.Apis |
NotificationApiClient | Notification.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.yamlHow 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:
- Review the diff to ensure no breaking changes were introduced silently.
- Update the package version in
pubspec.yaml. - Commit and push to the
MobileAPIClientsrepo. - In each consuming app, run
melos run getto 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
| Category | Examples |
|---|---|
| Auth | MicrotecAuthService — Keycloak PKCE flow using flutter_appauth, token storage, refresh |
| Storage | SecureTokenStorage — flutter_secure_storage wrapper; AppPreferences — shared_preferences wrapper |
| Base classes | BaseScreen (StatefulWidget with standard lifecycle), BaseBloc, BaseRepository |
| Sync | SyncManager, SyncQueue, ConnectivityWatcher — offline sync infrastructure |
| Network | MicrotecHttpClient — Dio instance pre-configured with the auth interceptor and base URL |
| Utilities | DateFormatter, CurrencyFormatter, PhoneNumberUtils, ValidationUtils |
| Constants | ApiPaths, StorageKeys, AppConstants |
| Exceptions | ApiException, 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.yamlUsing 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
- Add the class to the appropriate subfolder in
lib/src/. - Export from the barrel:
lib/microtec_shared.dart. - Write unit tests in
test/. - Update the version in
pubspec.yaml. - Commit to the
MobileSharedComprepo. - Run
melos run getin 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-apkUpdating 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 initChecking submodule status
bash
git submodule statusA + 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.