Colveor

A Flutter foundation package for building production-ready mobile apps. Colveor provides authentication flows, networking, push notifications, and app bootstrap on top of colveor_ui — so you can focus on your product screens instead of rebuilding common infrastructure.

The UI toolkit (widgets, theming, routing) lives in colveor_ui, which apps that don't need the API or auth layer can use on its own. Colveor depends on it and re-exports it, so apps built on Colveor only import package:colveor/....

The example/ app shows how to wire everything together.

Features

  • Authentication — phone sign-in/sign-up, OTP verification, session storage, and token refresh
  • Networking — Dio-based API client with interceptors, DPoP proofs, error handling, and secure token storage
  • Notifications — Firebase Cloud Messaging setup, permission prompt, and device registration
  • Bootstrap — Firebase and network initialization on top of the colveor_ui bootstrap
  • From colveor_ui — UI toolkit, theming with light/dark mode, and go_router routing with redirect callbacks
  • State management — Riverpod with generated providers

Project structure

colveor/
├── lib/                              # The package (imported by your app)
│   ├── colveor.dart                  # Main entry — bootstrap, ColveorApp, ColveorRef
│   ├── auth.dart                     # Auth module exports
│   ├── notifications.dart            # Notifications module exports
│   ├── config.dart                   # VoConfig, Firebase config, interceptor hooks
│   ├── extensions.dart               # colveor_ui extensions + auth/controller extensions
│   ├── theme.dart, routing.dart,     # Re-exports of colveor_ui
│   │   utils.dart, widgets/*.dart
│   └── src/
│       ├── core/                     # Foundation layer
│       │   ├── bootstrap/            # Firebase & network setup
│       │   ├── config/               # VoConfig (extends colveor_ui's VoConfig)
│       │   ├── errors/               # Exceptions & API error responses
│       │   ├── models/               # Pagination & file models
│       │   ├── network/              # API client, interceptors, DPoP, tokens
│       │   └── utils/                # JWT helper
│       ├── modules/                  # Feature modules
│       │   ├── auth/                 # Auth services, controllers, and UI
│       │   └── notifications/        # Push notification controller & services
│       └── ui/extensions/            # Auth & controller BuildContext extensions
│
└── example/                          # Demo app using the package
    └── lib/
        ├── main.dart                 # App entry point
        ├── config/                   # App-specific config
        ├── theme/                    # App-specific colors & typography
        ├── routes/                   # App-specific routes
        └── modules/                  # App-specific screens
Layer Role
colveor_ui Widgets, theme, routing, base widgets, formatters, country data
lib/src/core/ API, auth and Firebase infrastructure
lib/src/modules/ Big features like authentication and notifications
example/ Your real app — config, theme, routes, and screens

Getting started

Prerequisites

  • Dart SDK ^3.12.2
  • Firebase is only needed if you use push notifications

Installation

Add colveor from pub.dev:

flutter pub add colveor

or add it to pubspec.yaml yourself:

dependencies:
  colveor: ^0.1.0

colveor_ui (^0.1.0) comes in as a dependency, so you don't need to add it.

To work against a local checkout instead, use a path dependency:

dependencies:
  colveor:
    path: ../colveor_flutter

Run the example app

cd example
flutter pub get
flutter run

Usage

1. Bootstrap the app

Call VoBootstrap.initialize() before runApp. It runs the colveor_ui bootstrap, then sets up Firebase (optional) and the network layer.

Country data for the phone input loads the first time VoPhoneInput or VoSelectCountryField is built. Pass preloadCountries: true to load it during bootstrap instead.

import 'package:colveor/colveor.dart';
import 'package:example/config/app_config.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await VoBootstrap.initialize(config: AppConfig());

  runApp(
    ColveorApp(
      config: AppConfig(),
      appRoutes: appRoutes,
      builder: (context, colveor) => App(colveor: colveor),
    ),
  );
}

2. Implement app config

Extend VoConfig in your app to provide API URLs, routing, and feature flags. Colveor's VoConfig extends the colveor_ui one, so the same object configures both layers; pass it to ColveorApp and it is read through voConfigProvider.

import 'package:colveor/config.dart';

class AppConfig extends VoConfig {
  @override
  String get appName => 'My App';

  @override
  String get apiBaseUrl => 'https://api.example.com';

  @override
  String get apiVersion => 'api/v1';

  @override
  VoRoutingConfig get routing => VoRoutingConfig(
    initialLocation: '/',
    // Optional: re-run redirects when auth state changes.
    onInit: (ref, notifier) =>
        ref.listen(authControllerProvider, (_, _) => notifier.notify()),
    // Optional: return a location to redirect, or null to continue.
    redirect: (ref, context, state) => null,
  );
}

3. Define your theme

Every theme part has a default. Subclass VoColors, VoSizes, VoTypography, or VoComponentTheme only where you need to brand, and return them from your VoTheme.

import 'package:colveor/theme.dart';

class AppColors extends VoColors {
  @override
  VoColorMode get primaryMode => VoColorMode(
    light: const Color(0xFF132B50),
    dark: const Color(0xFF4DA3FF),
  );
  // ... override other color modes
}

class AppTheme extends VoTheme {
  const AppTheme();

  @override
  VoColors get colors => const AppColors();
}

Wire the theme into MaterialApp.router:

class App extends StatelessWidget {
  final ColveorRef colveor;
  const App({super.key, required this.colveor});

  @override
  Widget build(BuildContext context) => MaterialApp.router(
    title: AppConfig().appName,
    theme: const AppTheme().light,
    darkTheme: const AppTheme().dark,
    themeMode: colveor.themeMode,
    routerConfig: colveor.router,
  );
}

4. Add routes

Define route path constants and pass a route list to ColveorApp. The router is created automatically from your routes and VoRoutingConfig.

import 'package:colveor/colveor.dart';

List<RouteBase> appRoutes(_) => [
  GoRoute(
    path: '/',
    builder: (context, state) => const SplashScreen(),
  ),
  GoRoute(
    path: '/login',
    builder: (context, state) => const AuthScreen(),
  ),
];

5. Set up authentication

Use VoAuthScreen with custom page builders for each step in the auth flow. The example app uses phone sign-in, OTP verification, and sign-up.

import 'package:colveor/auth.dart';
import 'package:colveor/colveor.dart';

class AuthScreen extends StatelessWidget {
  const AuthScreen({super.key});

  @override
  Widget build(BuildContext context) => Scaffold(
    body: VoAuthScreen(
      initialPage: VoAuthPageKeys.phoneSignIn,
      pages: VoAuthPages.phone(
        phoneBuilder: (_) => const PhoneSignInPage(),
        verifyOtpBuilder: (_) => const VerifyOtpPage(),
        signUpBuilder: (_) => const PhoneSignUpPage(),
      ),
      onAuthSuccess: (_, _) => context.vo.pushReplace('/home'),
    ),
  );
}

Inside auth pages, access the auth context and Colveor widgets:

import 'package:colveor/auth.dart';
import 'package:colveor/widgets/buttons.dart';
import 'package:colveor/widgets/inputs.dart';

class PhoneSignInPage extends StatefulWidget {
  const PhoneSignInPage({super.key});
  @override
  State<PhoneSignInPage> createState() => _PhoneSignInPageState();
}

class _PhoneSignInPageState extends VoState<PhoneSignInPage> {
  final _phoneController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    final auth = VoAuthScope.of(context);

    return VoPhoneInput(
      controller: _phoneController,
      options: const VoFieldOptions(label: 'Phone'),
    );
    // ...
  }
}

6. Use UI widgets

Import widgets from the public widgets/ barrel files (re-exported from colveor_ui):

import 'package:colveor/widgets/buttons.dart';   // VoButton, VoIconButton
import 'package:colveor/widgets/inputs.dart';    // VoTextField, VoPhoneInput, VoPinInput, ...
import 'package:colveor/widgets/layout.dart';    // VoScaffold, VoScrollableForm, VoTile, ...
import 'package:colveor/widgets/display.dart';    // VoText, VoAvatar, VoDivider, ...
import 'package:colveor/widgets/overlay.dart';    // Dialogs, bottom sheets, overlay lists
import 'package:colveor/widgets/feedback.dart';   // VoToast, feedback views, countdown actions
import 'package:colveor/widgets/page_flow.dart';  // Multi-step page flows
import 'package:colveor/widgets/dashboard.dart';  // VoDashboardShell, VoDashboardPane

7. Use the context helpers

In any widget, context.vo gives you the theme, screen size, navigation, and toast helpers for that context:

class MyScreen extends StatelessWidget {
  const MyScreen({super.key});

  @override
  Widget build(BuildContext context) => VoButton(
    label: 'Go home',
    onPressed: () => context.vo.pushReplace('/home'),
  );
}

In a State, extend VoState (or VoConsumerState with Riverpod) to use the same helpers as members, e.g. pushReplace('/home').

8. Adjust screen scaling

ColveorApp scales sizes against a 360×690 design by default. Pass designSize (and optionally minTextAdapt / splitScreenMode) to match your designs:

ColveorApp(
  config: AppConfig(),
  appRoutes: appRoutes,
  designSize: const Size(390, 844),
  builder: (context, colveor) => App(colveor: colveor),
)

Public API overview

Import What you get
package:colveor/colveor.dart ColveorApp, VoBootstrap, ColveorRef, VoConfig, VoState / VoConsumerState, everything in routing.dart
package:colveor/auth.dart Auth controllers, services, VoAuthScreen, VoAuthContext
package:colveor/notifications.dart Notification controller, permission prompt
package:colveor/config.dart VoConfig, VoRoutingConfig, VoFirebaseConfig, VoInterceptorHooks, Environment
package:colveor/extensions.dart colveor_ui extensions (context.vo, context.colorScheme, ...), plus context.currentUser, context.logout(), context.voConfig
package:colveor/theme.dart VoTheme, VoColors, VoSizes, VoTypography (colveor_ui)
package:colveor/routing.dart voRouterProvider, voNavigatorKey, go_router types (colveor_ui)
package:colveor/utils.dart VoLogger, VoValidators, formatters (colveor_ui)
package:colveor/widgets/*.dart UI components grouped by category (colveor_ui)

Import from package:colveor/... only. Importing package:colveor_ui/... alongside it causes name clashes, because both define VoConfig and VoBootstrap.

Environment flavors

Set the build flavor via --dart-define:

flutter run --dart-define=FLAVOR=production

Defaults to development when not set. Read the current environment with Environment.current.

Additional information

  • See the example/ app for a full working integration
  • Auth API endpoints are configured via VoConfig.endpoints — override in your AppConfig if your backend paths differ
  • Firebase and push notifications are optional — set firebaseConfig in your config when needed

License

MIT — see LICENSE.