initProject function
void
initProject()
Implementation
void initProject() async {
final currentDir = Directory.current;
// check if pubspec.yaml exists
final pubspecFile = File('${currentDir.path}/pubspec.yaml');
if (!pubspecFile.existsSync()) {
print(
'Error: pubspec.yaml file not found. Please run this command inside a Flutter project.');
exit(1);
}
// check if lib directory exits
final libDir = Directory('${currentDir.path}/lib');
if (!libDir.existsSync()) {
print(
'Error: lib/ directory not found. Please run this command inside a Flutter project.');
exit(1);
}
await addDependencies(currentDir.path);
final result = await Process.run('flutter', ['pub', 'get'],
workingDirectory: currentDir.path);
if (result.exitCode == 0) {
print('Dependencies installed successfully!');
} else {
print('Error while running flutter pub get: ${result.stderr}');
}
// create main.dart file with the necessary setup
final mainFile = File('lib/main.dart');
mainFile.createSync(recursive: true);
mainFile.writeAsStringSync('''
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'app.dart';
import 'core/utils/bloc_observer.dart';
import 'dependency_injector.dart';
FutureOr<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
// Ensure that the dependencies are initialized
await initializeDependencies();
Bloc.observer = MyAppBlocObserver();
runApp(const App());
}
''');
print('main.dart file re-written successfully.');
// Create app.dart file with MaterialApp.router
final appFile = File('lib/app.dart');
appFile.createSync(recursive: true);
appFile.writeAsStringSync('''
import 'package:flutter/material.dart';
import 'package:brave/config/theme/theme.dart';
import 'config/route/app_router.dart';
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context){
return MaterialApp.router(
darkTheme: darkTheme,
theme: lightTheme,
routerConfig:router,
debugShowCheckedModeBanner: false,
);
}
}
''');
print('app.dart file created successfully.');
print('app_router.dart file created successfully.');
// add dependency_injector.dart file
createFile(libDir.path, "dependency_injector.dart", '''
// if you want to use this code, please first add
// get_it package to your project by running
// flutter pub add get_it
import 'package:get_it/get_it.dart';
final sl = GetIt.instance;
Future<void> initializeDependencies() async {
// register your dependencies here...
}
''');
final featureDir = Directory('${libDir.path}/features');
featureDir.createSync(recursive: true);
print('Clean architecture folder structure created');
print(' - lib/features');
// create config folder
final configDir = Directory('${libDir.path}/config');
configDir.createSync(recursive: true);
// create sub-folders for config
Directory('${configDir.path}/route').createSync(recursive: true);
Directory('${configDir.path}/theme').createSync(recursive: true);
// create core folder
final coreDir = Directory('${libDir.path}/core');
coreDir.createSync(recursive: true);
// create sub-folders for core
Directory('${coreDir.path}/assets').createSync(recursive: true);
Directory('${coreDir.path}/colors').createSync(recursive: true);
Directory('${coreDir.path}/database').createSync(recursive: true);
Directory('${coreDir.path}/network').createSync(recursive: true);
Directory('${coreDir.path}/resources').createSync(recursive: true);
Directory('${coreDir.path}/utils').createSync(recursive: true);
Directory('${coreDir.path}/widgets').createSync(recursive: true);
// Generate theme file
createFile("${configDir.path}/theme", 'theme.dart', '''
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../core/colors/app_colors.dart';
final AppBarTheme appBarTheme = AppBarTheme(
systemOverlayStyle: SystemUiOverlayStyle.light,
backgroundColor: AppColors.primaryColor,
surfaceTintColor: AppColors.primaryColor,
elevation: 0,
centerTitle: false,
iconTheme: const IconThemeData(color: AppColors.primaryLight),
titleTextStyle: GoogleFonts.roboto(
fontSize: 20,
fontWeight: FontWeight.w600,
),
);
TextButtonThemeData textButtonTheme = TextButtonThemeData(
style: ButtonStyle(
elevation: WidgetStateProperty.all<double>(0),
foregroundColor: WidgetStateProperty.resolveWith<Color>(
(Set<WidgetState> state) => state.contains(WidgetState.disabled)
? AppColors.blackColor
: AppColors.blackColor,
),
backgroundColor: WidgetStateProperty.resolveWith<Color>(
(Set<WidgetState> state) =>
state.contains(WidgetState.disabled) ? Colors.white54 : Colors.white,
),
textStyle: WidgetStateProperty.all<TextStyle>(
GoogleFonts.inter(
fontSize: 15,
fontWeight: FontWeight.w500,
letterSpacing: 0.6,
),
),
shape: WidgetStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
side: const BorderSide(
color: Colors.grey,
width: 0.3,
),
borderRadius: BorderRadius.circular(4.0),
),
),
));
ThemeData lightTheme = ThemeData(
useMaterial3: true,
colorScheme: lightColorScheme,
appBarTheme: appBarTheme,
textButtonTheme: textButtonTheme,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
elevation: WidgetStateProperty.all<double>(0),
minimumSize:
WidgetStateProperty.all<Size>(const Size(double.infinity, 48)),
backgroundColor: WidgetStateProperty.resolveWith<Color>(
(Set<WidgetState> state) => state.contains(WidgetState.disabled)
? AppColors.lightGrey
: AppColors.primaryColor,
),
foregroundColor: WidgetStateProperty.resolveWith<Color>(
(Set<WidgetState> state) => state.contains(WidgetState.disabled)
? AppColors.darkGrey
: Colors.white,
),
textStyle: WidgetStateProperty.all<TextStyle>(
GoogleFonts.inter(
fontSize: 15,
fontWeight: FontWeight.w500,
letterSpacing: 0.6,
),
),
shape: WidgetStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
),
textTheme: textTheme.apply(bodyColor: AppColors.primaryColor),
inputDecorationTheme: InputDecorationTheme(
labelStyle: GoogleFonts.roboto(
fontWeight: FontWeight.w400,
fontSize: 16,
color: AppColors.blackColor,
),
floatingLabelStyle: GoogleFonts.roboto(
fontWeight: FontWeight.w400,
color: AppColors.blackColor,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey.shade500, width: 0.1),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey.shade500, width: 1),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: const BorderSide(color: AppColors.primaryColor, width: 2),
),
),
floatingActionButtonTheme: FloatingActionButtonThemeData(
foregroundColor: Colors.white,
backgroundColor: AppColors.primaryColor,
extendedTextStyle: GoogleFonts.inter(
fontSize: 15,
fontWeight: FontWeight.w500,
letterSpacing: 0.6,
),
),
);
ThemeData darkTheme = ThemeData(
useMaterial3: true,
colorScheme: darkColorScheme,
// scaffoldBackgroundColor: AppColors.blackColor,
appBarTheme: appBarTheme,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
elevation: WidgetStateProperty.all<double>(0),
backgroundColor: WidgetStateProperty.resolveWith<Color>(
(Set<WidgetState> state) => state.contains(WidgetState.disabled)
? Colors.grey
: AppColors.primaryColor,
),
foregroundColor: WidgetStateProperty.resolveWith<Color>(
(Set<WidgetState> state) => state.contains(WidgetState.disabled)
? Colors.white60
: Colors.white,
),
textStyle: WidgetStateProperty.all<TextStyle>(
GoogleFonts.inter(
fontSize: 15,
fontWeight: FontWeight.w500,
),
),
shape: WidgetStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
),
),
textTheme: textTheme.apply(bodyColor: Colors.white),
inputDecorationTheme: InputDecorationTheme(
labelStyle: GoogleFonts.roboto(
fontWeight: FontWeight.w400,
fontSize: 16,
color: Colors.white60,
),
floatingLabelStyle: GoogleFonts.roboto(
fontWeight: FontWeight.w400,
color: Colors.white60,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey.shade500, width: 0.1),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: BorderSide(color: Colors.grey.shade500, width: 1),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(5),
borderSide: const BorderSide(color: Colors.white60, width: 2),
),
),
scaffoldBackgroundColor: AppColors.primaryColor,
floatingActionButtonTheme: FloatingActionButtonThemeData(
foregroundColor: Colors.white,
backgroundColor: AppColors.primaryColor,
extendedTextStyle: GoogleFonts.inter(
fontSize: 15,
fontWeight: FontWeight.w500,
letterSpacing: 0.6,
),
),
);
// Color Schemes
const lightColorScheme = ColorScheme(
brightness: Brightness.light,
primary: Color(0xFF6750A4),
onPrimary: Color(0xFFFFFFFF),
primaryContainer: Color(0xFFEADDFF),
onPrimaryContainer: Color(0xFF21005D),
secondary: Color(0xFF625B71),
onSecondary: Color(0xFFFFFFFF),
secondaryContainer: Color(0xFFE8DEF8),
onSecondaryContainer: Color(0xFF1D192B),
tertiary: Color(0xFF7D5260),
onTertiary: Color(0xFFFFFFFF),
tertiaryContainer: Color(0xFFFFD8E4),
onTertiaryContainer: Color(0xFF31111D),
error: Color(0xFFB3261E),
onError: Color(0xFFFFFFFF),
errorContainer: Color(0xFFF9DEDC),
onErrorContainer: Color(0xFF410E0B),
outline: Color(0xFF79747E),
surface: Color(0xFFFFFBFE),
onSurface: Color(0xFF1C1B1F),
surfaceContainerHighest: Color(0xFFE7E0EC),
onSurfaceVariant: Color(0xFF49454F),
inverseSurface: Color(0xFF313033),
onInverseSurface: Color(0xFFF4EFF4),
inversePrimary: Color(0xFFD0BCFF),
shadow: Color(0xFF000000),
surfaceTint: Color(0xFF6750A4),
outlineVariant: Color(0xFFCAC4D0),
scrim: Color(0xFF000000),
);
const darkColorScheme = ColorScheme(
brightness: Brightness.dark,
primary: Color(0xFFD0BCFF),
onPrimary: Color(0xFF381E72),
primaryContainer: Color(0xFF4F378B),
onPrimaryContainer: Color(0xFFEADDFF),
secondary: Color(0xFFCCC2DC),
onSecondary: Color(0xFF332D41),
secondaryContainer: Color(0xFF4A4458),
onSecondaryContainer: Color(0xFFE8DEF8),
tertiary: Color(0xFFEFB8C8),
onTertiary: Color(0xFF492532),
tertiaryContainer: Color(0xFF633B48),
onTertiaryContainer: Color(0xFFFFD8E4),
error: Color(0xFFF2B8B5),
onError: Color(0xFF601410),
errorContainer: Color(0xFF8C1D18),
onErrorContainer: Color(0xFFF9DEDC),
outline: Color(0xFF938F99),
surface: Color(0xFF1C1B1F),
onSurface: Color(0xFFE6E1E5),
surfaceContainerHighest: Color(0xFF49454F),
onSurfaceVariant: Color(0xFFCAC4D0),
inverseSurface: Color(0xFFE6E1E5),
onInverseSurface: Color(0xFF313033),
inversePrimary: Color(0xFF6750A4),
shadow: Color(0xFF000000),
surfaceTint: Color(0xFFD0BCFF),
outlineVariant: Color(0xFF49454F),
scrim: Color(0xFF000000),
);
final textTheme = TextTheme(
titleLarge: GoogleFonts.roboto(
fontWeight: FontWeight.w700,
fontSize: 20,
),
titleMedium: GoogleFonts.roboto(
fontWeight: FontWeight.w600,
fontSize: 18,
),
titleSmall: GoogleFonts.roboto(
fontWeight: FontWeight.w500,
fontSize: 16,
),
bodyMedium: GoogleFonts.roboto(
fontWeight: FontWeight.w400,
fontSize: 12,
),
bodySmall: GoogleFonts.roboto(
fontWeight: FontWeight.w400,
fontSize: 10,
),
labelMedium: GoogleFonts.roboto(
fontWeight: FontWeight.w400,
fontSize: 16,
letterSpacing: 0.8,
),
headlineMedium: GoogleFonts.roboto(
fontWeight: FontWeight.w600,
fontSize: 16,
),
headlineSmall: GoogleFonts.roboto(
fontWeight: FontWeight.w500,
fontSize: 14,
),
labelLarge: GoogleFonts.roboto(
fontWeight: FontWeight.w700,
fontSize: 13,
),
);
''');
// Generate router file
createFile("${configDir.path}/route", 'app_router.dart', '''
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
GlobalKey<NavigatorState> _rootNavigatorKey = GlobalKey<NavigatorState>();
GlobalKey<NavigatorState> _shellNavigatorKey = GlobalKey<NavigatorState>();
GoRouter router = GoRouter(
debugLogDiagnostics: true,
navigatorKey: _rootNavigatorKey,
initialLocation: '/',
routes: [
],
);
''');
// Generate colors
createFile("${coreDir.path}/colors", 'app_colors.dart', '''
import 'package:flutter/material.dart';
class AppColors {
// replace these colors with your own colors
// you can customize the [names] as you want
static const Color primaryColor = Color(0xFF16423C);
static const Color secondaryColor = Color(0xFF6A9C89);
static const Color tertiaryColor = Color(0xFFC4DAD2);
static const Color cardBackgroundColor = Color(0xFF031634);
static const Color primaryLight = Color(0xFFFBF8EF);
static const Color blackColor = Color(0xFF000f26);
static const Color appRedColor = Color(0xFFA04747);
static const Color whiteAppColor = Color(0xFFFFFFFF);
static const Color dark = Color(0xFF262626);
static const darkGrey = Color(0xFF686868);
static const lightGrey = Color(0xFFE0E0E0);
static const Color disabled = Color(0xFFC7C8CC);
static const Color splashBackgroundColor = Color(0XFFf1efe7);
}
''');
// Generate local db service
createFile("${coreDir.path}/database", 'local_db_service.dart', '''
class LocalDBService {
// your local database code goes here...
}
''');
// Generate bloc observer file
createFile("${coreDir.path}/utils", 'bloc_observer.dart', '''
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class MyAppBlocObserver extends BlocObserver {
@override
void onTransition(Bloc bloc, Transition transition) {
log('onTransition: \$transition');
super.onTransition(bloc, transition);
}
@override
void onEvent(Bloc bloc, Object? event) {
log('OnEvent: \$event');
super.onEvent(bloc, event);
}
@override
void onCreate(BlocBase bloc) {
super.onCreate(bloc);
debugPrint('onCreate: \${bloc.runtimeType}');
}
@override
void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
super.onError(bloc, error, stackTrace);
debugPrint('onError: \${bloc.runtimeType}, \$error');
}
}
''');
// Create Default Helper Files
final helperDir = Directory('${libDir.path}/helpers');
helperDir.createSync(recursive: true);
final apiHelper = File('${helperDir.path}/api_helper.dart');
apiHelper.writeAsString('''
class ApiHelper {
// Your API helper methods here
}
''');
print('Helper file created: lib/helpers/api_helper.dart');
final validators = File('${helperDir.path}/validators.dart');
validators.writeAsString('''
class Validators {
static String? validateEmail(String email) {
if (email.isEmpty) return 'Email is required.';
final regex = RegExp(r'^\S+@\S+\.\S+\$');
return regex.hasMatch(email) ? null : 'Invalid email format';
}
}
''');
print('Helper file created: lib/helpers/validators.dart');
final configFile = File('${currentDir.path}/initpro_config.yaml');
configFile.writeAsString('''
# Configuration fro InitPro CLI Tool
state_management: bloc
use_themes:true
''');
print('Configuration file created: initpro_config.yaml');
}