nets_core
Modern Flutter foundations for Nets apps. nets_core packages the shared UI, services, app shell, storage, notifications, localisation, and utilities that Nets projects use to start consistent and move faster.
What You Get
nets_core is the common layer for Flutter applications in the Nets ecosystem. It keeps repeated product work out of each app and gives teams a reliable base for navigation, forms, secure data, API calls, notifications, and platform utilities.
| Area | Included |
|---|---|
| App shell | AppStack, AppStackMenuItem, go_router integration, convex bottom navigation |
| UI | Buttons, profile avatars, loading screens, decorated lists, sliver headers, gradient helpers |
| Layouts | Fullscreen, sticky header/body, stepper, progress-step layouts |
| Forms | Declarative form builder and styled text inputs |
| Camera | Ready-to-use picture capture and preview flow |
| Networking | URL registry, authenticated requests, cookies, multipart uploads, development certificates |
| Storage | Secure key-value helpers backed by flutter_secure_storage |
| Notifications | Local notifications and Firebase Cloud Messaging helpers |
| State | Riverpod state notifier with selective secure persistence |
| Utilities | Device info, country helpers, string extensions, package localisations |
Installation
Add the package to your app:
dependencies:
nets_core: ^0.1.15
Then fetch dependencies:
flutter pub get
Requirements
| Tool | Version |
|---|---|
| Dart SDK | ^3.5.0 |
| Flutter | Compatible with the Dart SDK above |
Some features depend on platform setup in the host app. Camera, push notifications, Firebase, and secure storage should be configured in the application that consumes this package.
Quick Start
App Shell
Use AppStack as the shared scaffold for apps that use bottom navigation with go_router.
AppStack(
title: 'Nets App',
menu: [
AppStackMenuItem(
label: 'Home',
icon: Icons.home,
location: '/home',
),
AppStackMenuItem(
label: 'Profile',
icon: Icons.person,
location: '/profile',
),
],
child: child,
)
Secure Storage
Store sensitive app values behind a small, predictable API.
final storage = StorageService();
await storage.writeSecureData('accessToken', token);
final savedToken = await storage.readSecureData('accessToken');
API Client
Define named routes once, then call them through ApiService.
final apiUrls = ApiUrls(
baseUrl: 'https://api.example.com',
baseUrlDev: 'https://dev.api.example.com',
baseMediaUrl: 'https://media.example.com',
baseMediaUrlDev: 'https://dev.media.example.com',
urls: [
BaseUrl(
name: 'users',
path: '/api/users/',
items: [
BaseUrl(name: 'detail', path: '/api/users/{id}/'),
],
),
],
);
final api = ApiService(
urls: apiUrls,
clientId: 'client-id',
clientSecret: 'client-secret',
);
final response = await api.get('users', {});
Camera Flow
Launch the built-in capture screen and receive the selected file when the user continues.
final cameras = await availableCameras();
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => TakePictureScreen(
camera: cameras.first,
title: 'Profile photo',
onPictureTaken: (file) {
// Upload or persist the captured image.
},
),
),
);
String Utilities
Use shared extensions for common display formatting.
'hello world'.capitalize; // Hello world
'hello world'.capitalizeFirstofEach; // Hello World
Platform Setup
Firebase
The notification stack expects Firebase to be initialised by the host app before Firebase Messaging is used.
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
Android
Add the permissions required by the features you enable.
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
iOS
Provide user-facing permission descriptions in Info.plist.
<key>NSCameraUsageDescription</key>
<string>Required for taking profile pictures.</string>
Package Map
lib/
app_stack.dart Navigation shell and menu model
components/ Reusable UI, layouts, forms, screens, widgets
l10n/ Package localisation delegates and strings
providers/ Riverpod state provider
services/ API URLs, network, notifications, storage
utils/ Country, device, and string helpers
Development
Run the standard Flutter checks before publishing changes.
flutter analyze
flutter test
dart pub publish --dry-run
Generated code is used for providers and JSON models. When annotations change, rebuild with:
dart run build_runner build --delete-conflicting-outputs
Release Flow
- Update
versioninpubspec.yaml. - Add the release notes to
CHANGELOG.md. - Run analysis, tests, and publish dry-run locally.
- Merge to
master. - Push a matching tag, for example
v0.1.15.
The repository publish workflow validates that the Git tag matches the package version before publishing to pub.dev.
Links
Libraries
- app_stack
- components/form/form_builder
- components/form/text_form_input
- components/layouts/fullscreen
- components/layouts/header_body_scroll
- components/layouts/main_layout
- components/layouts/page_stepper
- components/layouts/progress_step_layout
- components/lists/list_decorated
- components/lists/options_list
- components/lists/options_list_item
- components/profile/profile_avatar
- components/screens/loading_screen
- components/take_picture_screen
- components/widgets/gradient_shader
- components/widgets/sliver_header
- components/widgets/sliver_header_generic
- components/widgets/webview
- l10n/app_localizations
- l10n/app_localizations_en
- l10n/localizations
- nets_core
- providers/nets_provider
- services/api_urls
- services/network_service
- services/notifications_service
- services/storage_service
- utils/country_utils
- utils/device_utils
- utils/extensions