Skip to content

NadeemIqbal/Flutter-ReactNative-BaseArch-CLI

Repository files navigation

Base Architecture Mobile App Generator

A Node.js CLI tool that automatically generates fully configured Flutter and React Native mobile applications from base architectures. This tool streamlines the setup process by handling project configuration, flavor management, Firebase integration, signing configurations, and more through a simple JSON configuration file.

TL;DR - Quick Commands

Just want to run it? Here are the essential commands:

# Test your configuration first (recommended)
node setup-app.js --dry-run

# Generate your projects
node setup-app.js

# Use a custom config file
node setup-app.js --config my-config.json

# Test with custom config
node setup-app.js --config my-config.json --dry-run

# Show help
node setup-app.js --help

What you need:

  1. A config.json file with your project settings
  2. Resource files in res_flutter/ and/or res_rn/ directories
  3. Base architecture (local folder or Git repository URL)

Output: Generated projects will be in the output/ directory.

For detailed information, see the sections below.

Quick Start

  1. Clone this repository or download the tool
  2. Prepare your resources in res_flutter/ and res_rn/ directories
  3. Create or edit config.json with your project settings
  4. Test your configuration: node setup-app.js --dry-run
  5. Generate your projects: node setup-app.js

Your generated projects will be in the output/ directory, ready to build and run.

Table of Contents

Overview

This tool automates the creation of mobile applications by:

  1. Cloning base architecture repositories (from Bitbucket/Git or local folders)
  2. Configuring project files (pubspec.yaml, package.json, build.gradle, etc.)
  3. Setting up multiple flavors (dev, stage, prod)
  4. Integrating Firebase configurations per flavor
  5. Copying environment files, icons, and assets
  6. Configuring Android and iOS signing
  7. Generating flavor-specific entry points and build configurations

The tool is deterministic, idempotent, and CI/CD safe, making it perfect for automated build pipelines.

How It Works

Execution Flow

  1. Configuration Loading: Reads config.json and validates all required fields and resources
  2. Base Architecture Cloning:
    • If baseArchPath is a Git URL, clones the repository to a temporary directory
    • If it's a local path, uses the existing folder
    • Automatically cleans up temporary clones after setup
  3. Project Setup:
    • Copies base architecture to output directory
    • Updates project configuration files
    • Creates flavor-specific entry points
  4. Platform Configuration:
    • Android: Configures Gradle, flavors, Firebase, icons, signing
    • iOS: Configures Xcode project, schemes, Firebase, icons, signing
  5. Resource Integration: Copies environment files, assets, and other resources
  6. Cleanup: Removes temporary cloned directories

Supported Platforms

  • Flutter: Full support for multi-flavor Flutter applications
  • React Native: Full support for multi-flavor React Native applications
  • Both platforms can be configured simultaneously or independently

Project Structure

base_arch/
├── setup-app.js                 # Main CLI entry point
├── config.json                  # Configuration file
├── lib/                         # Core library code
│   ├── core/                    # Core utilities
│   │   ├── config-loader.js    # Configuration parser
│   │   ├── validator.js         # Configuration validator
│   │   ├── fs-wrapper.js        # File system operations
│   │   ├── git-clone.js         # Git repository cloning
│   │   └── logger.js            # Logging utility
│   ├── flutter/                 # Flutter-specific setup
│   │   ├── index.js             # Flutter orchestrator
│   │   ├── project.js           # Project file updates
│   │   ├── android.js           # Android configuration
│   │   ├── ios.js               # iOS configuration
│   │   ├── env.js               # Environment files
│   │   └── assets.js            # Asset copying
│   └── react-native/            # React Native-specific setup
│       ├── index.js             # React Native orchestrator
│       ├── project.js            # Project file updates
│       ├── android.js            # Android configuration
│       ├── ios.js               # iOS configuration
│       └── env.js               # Environment files
├── basearch_flutter/            # Local Flutter base architecture (optional)
│   └── base_project_flutter/    # Flutter project template
├── basearch_rn/                 # Local React Native base architecture (optional)
├── res_flutter/                 # Flutter resources
│   ├── firebase/                # Firebase configs per flavor
│   ├── env/                     # Environment files per flavor
│   ├── icons/                    # App icons per flavor
│   ├── assets/                  # Common assets
│   └── signing/                 # Signing certificates
├── res_rn/                      # React Native resources
│   ├── firebase/                # Firebase configs per flavor
│   ├── env/                     # Environment files per flavor
│   ├── icons/                   # App icons per flavor
│   └── signing/                 # Signing certificates
└── output/                      # Generated projects (created by tool)
    ├── flutter/
    │   └── project_name/
    └── rn/
        └── project_name/

Installation

Prerequisites

  • Node.js (v14 or higher)
  • Git (for cloning repositories)
  • For Flutter: Flutter SDK
  • For React Native: React Native development environment

Setup

  1. Clone or download this repository

    git clone <repository-url>
    cd base_arch
  2. Verify Node.js installation

    node --version  # Should be v14 or higher
  3. No additional npm packages required - The tool uses only Node.js built-in modules

  4. Ensure Git is installed (if using Git URLs for base architectures)

    git --version
  5. Prepare access to base architecture repositories (if using Git URLs)

    • For HTTPS: Have your Bitbucket/GitHub credentials ready (App Password or token)
    • For SSH: Ensure SSH keys are configured and added to your Git provider

Configuration

The tool is configured entirely through a JSON file (default: config.json). The configuration is divided into several sections:

  • meta: Project metadata and output settings
  • flavors: List of flavors to generate
  • common: Shared configuration across platforms
  • flutter: Flutter-specific configuration
  • reactNative: React Native-specific configuration

Directory Structure and File Placement

Resource Files Location

All resource files must be placed in the appropriate directories relative to your config.json file:

Flutter Resources (res_flutter/)

res_flutter/
├── firebase/
│   ├── dev/
│   │   ├── google-services.json          # Android Firebase config
│   │   └── GoogleService-Info.plist     # iOS Firebase config
│   ├── stage/
│   │   ├── google-services.json
│   │   └── GoogleService-Info.plist
│   └── prod/
│       ├── google-services.json
│       └── GoogleService-Info.plist
├── env/
│   ├── .env.dev                          # Development environment variables
│   ├── .env.stage                        # Staging environment variables
│   └── .env.prod                         # Production environment variables
├── icons/
│   ├── dev/
│   │   ├── android/                      # Android launcher icons
│   │   │   ├── mipmap-mdpi/
│   │   │   ├── mipmap-hdpi/
│   │   │   ├── mipmap-xhdpi/
│   │   │   ├── mipmap-xxhdpi/
│   │   │   ├── mipmap-xxxhdpi/
│   │   │   └── mipmap-anydpi-v26/
│   │   └── ios/                          # iOS app icons
│   │       └── AppIcon.appiconset/
│   ├── stage/
│   │   ├── android/
│   │   └── ios/
│   └── prod/
│       ├── android/
│       └── ios/
├── assets/
│   └── common/                           # Common assets (images, fonts, etc.)
└── signing/
    ├── android/
    │   ├── dev/
    │   │   └── keystore.jks             # Android keystore file
    │   ├── stage/
    │   │   └── keystore.jks
    │   └── prod/
    │       └── keystore.jks
    └── ios/
        ├── dev/
        │   └── profile.mobileprovision  # iOS provisioning profile
        ├── stage/
        │   └── profile.mobileprovision
        └── prod/
            └── profile.mobileprovision

React Native Resources (res_rn/)

res_rn/
├── firebase/
│   ├── dev/
│   │   ├── google-services.json
│   │   └── GoogleService-Info.plist
│   ├── stage/
│   └── prod/
├── env/
│   ├── .env.dev
│   ├── .env.stage
│   └── .env.prod
├── icons/
│   ├── dev/
│   │   ├── android/
│   │   └── ios/
│   ├── stage/
│   └── prod/
└── signing/
    ├── android/
    │   ├── dev/
    │   ├── stage/
    │   └── prod/
    └── ios/
        ├── dev/
        ├── stage/
        └── prod/

Base Architecture Location

You have two options for base architectures:

Option 1: Local Folders

Place your base architecture folders in the project root:

base_arch/
├── basearch_flutter/
│   └── base_project_flutter/    # Your Flutter project template
└── basearch_rn/                  # Your React Native project template

Then in config.json:

{
  "flutter": {
    "baseArchPath": "basearch_flutter"
  },
  "reactNative": {
    "baseArchPath": "basearch_rn"
  }
}

Option 2: Git Repositories (Recommended)

Use Git URLs in config.json:

{
  "flutter": {
    "baseArchPath": "https://username:token@bitbucket.org/workspace/flutter-repo.git",
    "baseArchBranch": "main"
  },
  "reactNative": {
    "baseArchPath": "https://username:token@bitbucket.org/workspace/rn-repo.git",
    "baseArchBranch": "main"
  }
}

The tool will automatically clone these repositories at runtime and clean them up afterward.

Usage

Basic Usage

# Run with default config.json
node setup-app.js

# Preview changes without making them (recommended first)
node setup-app.js --dry-run

# Use a custom config file
node setup-app.js --config my-config.json

# Combine options
node setup-app.js --config production.json --dry-run

# Show help
node setup-app.js --help

Command Line Options

  • --dry-run or -d: Preview all changes without modifying the filesystem. Useful for testing configuration before actual execution.
  • --config or -c <path>: Specify a custom configuration file path. Default is config.json.
  • --help or -h: Display help message and exit.

Typical Workflow

  1. Prepare Resources: Place all required files in res_flutter/ and res_rn/ directories according to the structure outlined in Directory Structure and File Placement

  2. Create Configuration: Create or edit config.json with your project settings. Start with a minimal configuration and add features incrementally.

  3. Test Configuration: Always run with --dry-run first to verify everything is correct:

    node setup-app.js --dry-run

    This will show you what would be created without making any changes.

  4. Fix Any Issues: Review the dry-run output and fix any validation errors or missing files.

  5. Generate Projects: Once dry-run passes, run without --dry-run to create the projects:

    node setup-app.js
  6. Review Output: Check the generated projects in the output/ directory:

    • Flutter: output/flutter/project_name/
    • React Native: output/rn/project_name/
  7. Build and Run: Navigate to the generated project and follow platform-specific build instructions.

Configuration Options Explained

Meta Configuration

{
  "meta": {
    "projectName": "super_app",           // Project name (used for folder names)
    "outputDirectory": "output",          // Where generated projects will be placed
    "dryRun": false,                      // Enable dry-run mode (can be overridden by CLI)
    "overwriteIfExists": true             // Overwrite existing output directory if it exists
  }
}

Field Descriptions:

  • projectName (required): Used to generate folder names and project identifiers. Special characters are automatically sanitized (e.g., "My App" becomes "my_app"). This name will appear in generated project folders.
  • outputDirectory (required): Relative path from config.json location where generated projects will be placed. Default is "output". Generated projects will be in {outputDirectory}/flutter/{projectName}/ and {outputDirectory}/rn/{projectName}/.
  • dryRun (optional): When true, no files are created or modified. Useful for testing configuration. Can be overridden by the --dry-run CLI flag. Default is false.
  • overwriteIfExists (optional): Controls behavior when output directory already exists. When false, the tool will throw an error if the output directory exists. When true, it will delete the existing directory and recreate it. Default is false.

Flavors

{
  "flavors": ["dev", "stage", "prod"]
}

Field Descriptions:

  • Defines the list of flavors (build variants) to generate for your application
  • Each flavor gets its own configuration (Firebase configs, icons, environment files, package names, etc.)
  • Common flavor names: dev, stage, prod, qa, beta, demo
  • At least one flavor is required
  • Flavor names are case-sensitive and must match exactly in all configuration sections
  • Each flavor listed here must have corresponding entries in:
    • common.appDisplayName
    • common.apiBaseUrl (if used)
    • Firebase configs (if useFirebase is enabled)
    • Environment files (if useEnvFiles is enabled)
    • Icons (if useCustomIcons is enabled)

Common Configuration

{
  "common": {
    "organization": "company",            // Organization name
    "appDisplayName": {                   // App display name per flavor
      "dev": "Super App Dev",
      "stage": "Super App Stage",
      "prod": "Super App"
    },
    "apiBaseUrl": {                       // API base URLs per flavor
      "dev": "https://api.dev.example.com",
      "stage": "https://api.stage.example.com",
      "prod": "https://api.example.com"
    }
  }
}

Field Descriptions:

  • organization (optional): Organization name used in package names and bundle identifiers. Typically your company or organization identifier.
  • appDisplayName (required): The name displayed on the device home screen and app launcher. Must have an entry for each flavor defined in the flavors array. This is what users see when they install your app.
  • apiBaseUrl (optional): API base URLs for each flavor. These can be referenced in your environment files or used directly in app configuration. Useful for pointing different flavors to different backend environments.

Flutter Configuration

Basic Settings

{
  "flutter": {
    "enabled": true,                      // Enable/disable Flutter generation
    "baseArchPath": "basearch_flutter",   // Local path or Git URL
    "baseArchBranch": "main",             // Git branch (if using Git URL)
    "baseArchUsername": null,             // Git username (optional, can use ENV:)
    "baseArchPassword": null,             // Git password/token (optional, can use ENV:)
    "resourcePath": "res_flutter"         // Path to Flutter resources
  }
}

Base Architecture Options:

  1. Local Path: "baseArchPath": "basearch_flutter"

    • Uses local folder at project root
    • Must contain base_project_flutter/ subfolder
  2. Git URL with Embedded Credentials:

    "baseArchPath": "https://username:token@bitbucket.org/workspace/repo.git",
    "baseArchBranch": "main"
    • Credentials embedded in URL
    • Branch specified separately
  3. Git URL with Separate Credentials:

    "baseArchPath": "https://bitbucket.org/workspace/repo.git",
    "baseArchBranch": "main",
    "baseArchUsername": "myuser",
    "baseArchPassword": "ENV:GIT_TOKEN"
    • Use ENV:VARIABLE_NAME to read from environment variables
    • More secure for CI/CD pipelines
  4. SSH URL:

    "baseArchPath": "git@bitbucket.org:workspace/repo.git",
    "baseArchBranch": "main"
    • Requires SSH keys to be configured
    • No credentials needed in config

Dart Configuration

{
  "dart": {
    "organizationImport": "com.company.superapp"  // Dart package organization
  }
}

Details:

  • Used in import statements (e.g., import 'package:com.company.superapp/core/...')
  • Should match your organization's package naming convention

Android Configuration

{
  "android": {
    "baseApplicationId": "com.company.superapp",  // Base package name
    "flavorSuffix": {                             // Suffix per flavor
      "dev": ".dev",
      "stage": ".stage",
      "prod": ""
    },
    "minSdk": 24,                                 // Minimum Android SDK version
    "targetSdk": 34,                              // Target Android SDK version
    "compileSdk": 34                              // Compile SDK version
  }
}

Details:

  • baseApplicationId: Base package identifier. Final package will be baseApplicationId + flavorSuffix
    • Example: com.company.superapp.dev for dev flavor
  • flavorSuffix: Added to baseApplicationId for each flavor. Empty string for production.
  • SDK versions: Must be valid Android SDK versions (typically 24-34)

iOS Configuration

{
  "ios": {
    "baseBundleId": "com.company.superapp",       // Base bundle identifier
    "flavorSuffix": {                             // Suffix per flavor
      "dev": ".dev",
      "stage": ".stage",
      "prod": ""
    },
    "deploymentTarget": "13.0",                   // Minimum iOS version
    "teamId": "XXXXXXXXXX"                        // Apple Developer Team ID
  }
}

Details:

  • baseBundleId: Base bundle identifier. Final bundle ID will be baseBundleId + flavorSuffix
  • deploymentTarget: Minimum iOS version (e.g., "13.0", "14.0")
  • teamId: Your Apple Developer Team ID (10 characters)

Firebase Configuration

{
  "firebase": {
    "android": {
      "dev": "res_flutter/firebase/dev/google-services.json",
      "stage": "res_flutter/firebase/stage/google-services.json",
      "prod": "res_flutter/firebase/prod/google-services.json"
    },
    "ios": {
      "dev": "res_flutter/firebase/dev/GoogleService-Info.plist",
      "stage": "res_flutter/firebase/stage/GoogleService-Info.plist",
      "prod": "res_flutter/firebase/prod/GoogleService-Info.plist"
    }
  }
}

Details:

  • Paths are relative to the location of config.json
  • Must provide both Android and iOS configs for each flavor if Firebase is enabled
  • Files are copied to the appropriate locations in the generated project

Environment Files

{
  "env": {
    "dev": "res_flutter/env/.env.dev",
    "stage": "res_flutter/env/.env.stage",
    "prod": "res_flutter/env/.env.prod"
  }
}

Details:

  • Environment files are copied to the project root
  • Flutter uses flutter_dotenv package to load these files
  • Each flavor gets its own .env.{flavor} file

Icons Configuration

{
  "icons": {
    "android": {
      "dev": "res_flutter/icons/dev/android",
      "stage": "res_flutter/icons/stage/android",
      "prod": "res_flutter/icons/prod/android"
    },
    "ios": {
      "dev": "res_flutter/icons/dev/ios",
      "stage": "res_flutter/icons/stage/ios",
      "prod": "res_flutter/icons/prod/ios"
    }
  }
}

Details:

  • Android icons: Directory containing mipmap folders with icon files
  • iOS icons: Directory containing AppIcon.appiconset/ with icon assets
  • Icons are copied to platform-specific locations

Assets Configuration

{
  "assets": {
    "copy": [
      {
        "from": "res_flutter/assets/common",
        "to": "assets"
      }
    ]
  }
}

Details:

  • from: Source path relative to config.json
  • to: Destination path relative to project root
  • Supports both files and directories
  • Multiple copy operations can be specified

Features Configuration

{
  "features": {
    "useFlavors": true,          // Enable multi-flavor support
    "useFirebase": true,         // Enable Firebase integration
    "useEnvFiles": true,         // Enable environment files
    "useCustomIcons": true       // Enable custom app icons
  }
}

Details:

  • useFlavors: When false, skips flavor-specific entry points and configurations
  • useFirebase: When false, skips Firebase file copying
  • useEnvFiles: When false, skips environment file copying
  • useCustomIcons: When false, skips icon copying

Signing Configuration

{
  "signing": {
    "android": {
      "dev": {
        "storeFile": "res_flutter/signing/android/dev/keystore.jks",
        "storePassword": "ENV:FLUTTER_DEV_KEYSTORE_PASSWORD",
        "keyAlias": "dev-key",
        "keyPassword": "ENV:FLUTTER_DEV_KEY_PASSWORD"
      }
    },
    "ios": {
      "dev": {
        "teamId": "XXXXXXXXXX",
        "provisioningProfile": "res_flutter/signing/ios/dev/profile.mobileprovision"
      }
    }
  }
}

Details:

  • Android:
    • storeFile: Path to keystore file (.jks)
    • storePassword: Keystore password (use ENV:VARIABLE_NAME for security)
    • keyAlias: Key alias name
    • keyPassword: Key password (use ENV:VARIABLE_NAME for security)
  • iOS:
    • teamId: Apple Developer Team ID
    • provisioningProfile: Path to provisioning profile file

React Native Configuration

React Native configuration follows the same structure as Flutter, with these differences:

  • No dart section (not applicable)
  • baseArchPath points directly to React Native project root (no subfolder needed)
  • Uses app.json and package.json instead of pubspec.yaml
  • Uses react-native-config for environment variables

Base Architecture Setup

Flutter Base Architecture Structure

Your Flutter base architecture repository should have this structure:

flutter-base-arch/
└── base_project_flutter/          # This folder name is required
    ├── lib/
    │   ├── main.dart
    │   └── ...
    ├── android/
    ├── ios/
    ├── pubspec.yaml
    └── ...

Important: The Flutter base architecture must contain a base_project_flutter/ subfolder. This is where your Flutter project code lives.

React Native Base Architecture Structure

Your React Native base architecture repository should have this structure:

rn-base-arch/                      # Root is the project
    ├── src/
    ├── android/
    ├── ios/
    ├── package.json
    ├── app.json
    └── ...

Important: The React Native base architecture root should be the project root directly (no subfolder needed).

Resource Files

Firebase Configuration Files

Android (google-services.json):

  • Download from Firebase Console
  • Place in res_flutter/firebase/{flavor}/google-services.json
  • One file per flavor

iOS (GoogleService-Info.plist):

  • Download from Firebase Console
  • Place in res_flutter/firebase/{flavor}/GoogleService-Info.plist
  • One file per flavor

Environment Files

Create .env.{flavor} files with your environment variables:

# res_flutter/env/.env.dev
API_URL=https://api.dev.example.com
API_KEY=dev_key_123
DEBUG=true

The tool will copy these to the project root as .env.dev, .env.stage, .env.prod.

App Icons

Android Icons:

  • Create icons for all densities: mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi
  • Place in res_flutter/icons/{flavor}/android/mipmap-{density}/
  • Include adaptive icon files in mipmap-anydpi-v26/

iOS Icons:

  • Create AppIcon.appiconset with all required sizes
  • Place in res_flutter/icons/{flavor}/ios/AppIcon.appiconset/
  • Include all sizes from 20x20 to 1024x1024

Signing Files

Android Keystore:

  • Generate keystore: keytool -genkey -v -keystore keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias your-alias
  • Place in res_flutter/signing/android/{flavor}/keystore.jks
  • Store passwords securely (use environment variables in config)

iOS Provisioning Profile:

  • Download from Apple Developer Portal
  • Place in res_flutter/signing/ios/{flavor}/profile.mobileprovision

Common Use Cases

Use Case 1: Starting a New Project

When starting a new mobile application project:

  1. Clone your base architecture repositories (or ensure they're accessible)
  2. Create a new config.json with your project details
  3. Set up resource folders with Firebase configs, icons, and environment files
  4. Run with --dry-run to validate
  5. Generate the project
  6. Start development in the generated project

Use Case 2: Creating Multiple Flavors

To create dev, stage, and production variants:

  1. Define all three flavors in the flavors array
  2. Provide separate Firebase configs, icons, and environment files for each
  3. Configure different package names/bundle IDs using flavorSuffix
  4. The tool will generate entry points and build configurations for each flavor

Use Case 3: Team Collaboration

For teams working together:

  1. Store base architectures in Git repositories (recommended)
  2. Use environment variables for all sensitive data
  3. Version control config.json (but not sensitive resource files)
  4. Document resource file requirements in team wiki/docs
  5. Use consistent naming conventions across the team

Use Case 4: CI/CD Pipeline Integration

For automated project generation:

  1. Store configuration as code in your repository
  2. Use CI/CD secrets for all credentials and passwords
  3. Run validation step with --dry-run before actual generation
  4. Archive generated projects as build artifacts
  5. Use Git URLs for base architectures to ensure version consistency

Examples

Example 1: Basic Flutter App with Git Repository

{
  "meta": {
    "projectName": "my_app",
    "outputDirectory": "output",
    "overwriteIfExists": true
  },
  "flavors": ["dev", "prod"],
  "common": {
    "organization": "mycompany",
    "appDisplayName": {
      "dev": "My App Dev",
      "prod": "My App"
    }
  },
  "flutter": {
    "enabled": true,
    "baseArchPath": "https://user:token@bitbucket.org/workspace/flutter-base.git",
    "baseArchBranch": "main",
    "resourcePath": "res_flutter",
    "android": {
      "baseApplicationId": "com.mycompany.myapp",
      "flavorSuffix": {
        "dev": ".dev",
        "prod": ""
      }
    },
    "ios": {
      "baseBundleId": "com.mycompany.myapp",
      "flavorSuffix": {
        "dev": ".dev",
        "prod": ""
      }
    },
    "features": {
      "useFlavors": true,
      "useFirebase": false,
      "useEnvFiles": true,
      "useCustomIcons": false
    }
  },
  "reactNative": {
    "enabled": false
  }
}

Example 2: React Native with Local Base Architecture

{
  "meta": {
    "projectName": "rn_app",
    "outputDirectory": "output"
  },
  "flavors": ["dev", "stage", "prod"],
  "reactNative": {
    "enabled": true,
    "baseArchPath": "basearch_rn",
    "resourcePath": "res_rn",
    "android": {
      "baseApplicationId": "com.company.rnapp",
      "flavorSuffix": {
        "dev": ".dev",
        "stage": ".stage",
        "prod": ""
      }
    },
    "features": {
      "useFirebase": true,
      "useEnvFiles": true,
      "useCustomIcons": true
    }
  },
  "flutter": {
    "enabled": false
  }
}

Example 3: Both Platforms with Full Features

{
  "meta": {
    "projectName": "super_app",
    "outputDirectory": "output"
  },
  "flavors": ["dev", "stage", "prod"],
  "common": {
    "organization": "company",
    "appDisplayName": {
      "dev": "Super App Dev",
      "stage": "Super App Stage",
      "prod": "Super App"
    },
    "apiBaseUrl": {
      "dev": "https://api.dev.example.com",
      "stage": "https://api.stage.example.com",
      "prod": "https://api.example.com"
    }
  },
  "flutter": {
    "enabled": true,
    "baseArchPath": "https://user:token@bitbucket.org/workspace/flutter-repo.git",
    "baseArchBranch": "main",
    "resourcePath": "res_flutter",
    "features": {
      "useFlavors": true,
      "useFirebase": true,
      "useEnvFiles": true,
      "useCustomIcons": true
    },
    "signing": {
      "android": {
        "prod": {
          "storeFile": "res_flutter/signing/android/prod/keystore.jks",
          "storePassword": "ENV:FLUTTER_PROD_KEYSTORE_PASSWORD",
          "keyAlias": "prod-key",
          "keyPassword": "ENV:FLUTTER_PROD_KEY_PASSWORD"
        }
      }
    }
  },
  "reactNative": {
    "enabled": true,
    "baseArchPath": "https://user:token@bitbucket.org/workspace/rn-repo.git",
    "baseArchBranch": "main",
    "resourcePath": "res_rn",
    "features": {
      "useFlavors": true,
      "useFirebase": true,
      "useEnvFiles": true,
      "useCustomIcons": true
    }
  }
}

Troubleshooting

Common Issues

1. "Base architecture folder not found"

Problem: The tool cannot find the base architecture folder.

Solutions:

  • If using local path: Verify the folder exists at the specified path relative to config.json
  • If using Git URL: Check your credentials and repository URL
  • For Flutter: Ensure base_project_flutter/ subfolder exists
  • Verify the path in config.json is correct

2. "Authentication failed" when cloning

Problem: Cannot authenticate with Git repository.

Solutions:

  • Verify your Bitbucket App Password is correct (not your account password)
  • Check that credentials are properly embedded in URL: https://username:token@host
  • For SSH: Ensure SSH keys are configured and added to Bitbucket
  • Try using environment variables instead of embedding credentials

3. "Resource folder not found"

Problem: Required resource files are missing.

Solutions:

  • Verify resourcePath in config matches your actual folder name
  • Ensure all required files exist for enabled features
  • Check file paths are relative to config.json location
  • Run with --dry-run to see which files are missing

4. "Branch not found"

Problem: Specified branch doesn't exist in repository.

Solutions:

  • Verify branch name is correct (case-sensitive)
  • List branches: git ls-remote --heads <repo-url>
  • Set baseArchBranch to null to use default branch
  • Check that the branch exists in the remote repository

5. "Output directory already exists"

Problem: Output directory exists and overwriteIfExists is false.

Solutions:

  • Set "overwriteIfExists": true in config
  • Or delete the existing output directory manually
  • Or use a different outputDirectory path

6. Validation Errors

Problem: Configuration validation fails.

Solutions:

  • Check that all required fields are present
  • Verify flavor names match between flavors array and individual configs
  • Ensure all enabled features have corresponding resource files
  • Review error messages for specific missing items

Getting Help

When encountering issues, follow these steps in order:

  1. Run with --dry-run first to see what would happen without making changes:

    node setup-app.js --config config.json --dry-run
  2. Check validation errors - The tool provides specific error messages pointing to exact issues. Read them carefully as they usually indicate:

    • Missing required fields
    • Incorrect file paths
    • Missing resource files
    • Configuration mismatches
  3. Verify file paths - All paths in config.json are relative to the config.json file location. Ensure:

    • Resource paths point to existing files
    • Base architecture paths are correct
    • All referenced files actually exist
  4. Check Git access - If using Git URLs:

    # Test HTTPS access
    git ls-remote https://username:token@bitbucket.org/workspace/repo.git
    
    # Test SSH access
    git ls-remote git@bitbucket.org:workspace/repo.git
  5. Verify permissions - Ensure you have:

    • Read access to all resource files and base architectures
    • Write access to the output directory
    • Execute permissions for Node.js and Git
  6. Check environment variables - If using ENV:VARIABLE_NAME:

    # Verify variable is set
    echo $GIT_TOKEN
    
    # Or on Windows
    echo %GIT_TOKEN%
  7. Review the logs - The tool provides detailed logging. Look for:

    • Warning messages about missing optional files
    • Error messages about required files
    • Success messages confirming operations

Debug Mode

Set DEBUG=true environment variable for detailed error output:

DEBUG=true node setup-app.js --config config.json

This will show full stack traces for errors, making it easier to identify issues.

Best Practices

Configuration Management

  1. Always test with --dry-run first before running the actual setup. This helps catch configuration errors early.

  2. Use environment variables for sensitive data (passwords, tokens, keystore passwords) instead of hardcoding them in config.json. Use the ENV:VARIABLE_NAME format.

  3. Version control your config.json but exclude sensitive resource files (keystores, provisioning profiles) from version control. Add them to .gitignore.

  4. Use Git URLs for base architectures to ensure consistency across team members and CI/CD pipelines. This ensures everyone uses the same base architecture version.

  5. Organize resources clearly following the directory structure guidelines. Consistent organization makes it easier for team members to find and update resources.

Development Workflow

  1. Test with minimal features first then enable additional features incrementally. Start with basic configuration, then add Firebase, then icons, then signing.

  2. Keep base architectures updated in their repositories. When you update your base architecture, all new projects will automatically use the latest version.

  3. Use descriptive project names that reflect the actual application. Avoid generic names like "app" or "test".

  4. Document your configuration with comments in JSON (though JSON doesn't support comments, consider maintaining a separate documentation file for complex configurations).

CI/CD Integration

  1. Use environment variables in CI/CD for all sensitive data. Set them as secrets in your CI/CD platform.

  2. Run validation in CI/CD before generating projects. Use --dry-run in your CI pipeline to validate configurations.

  3. Cache base architecture clones in CI/CD if possible to speed up builds, though the tool automatically cleans up temporary clones.

  4. Generate projects in isolated environments to avoid conflicts between different project generations.

Output Structure

After running the tool, your generated projects will be in:

output/
├── flutter/
│   └── project_name/          # Flutter project
│       ├── lib/
│       │   ├── main.dart
│       │   ├── main_dev.dart  # Flavor-specific entry points
│       │   ├── main_stage.dart
│       │   ├── main_prod.dart
│       │   └── ...
│       ├── android/
│       │   ├── app/
│       │   │   ├── build.gradle
│       │   │   └── src/
│       │   └── ...
│       ├── ios/
│       │   ├── Runner.xcodeproj
│       │   └── ...
│       ├── .env.dev           # Environment files
│       ├── .env.stage
│       ├── .env.prod
│       └── pubspec.yaml
└── rn/
    └── project_name/          # React Native project
        ├── src/
        ├── android/
        │   ├── app/
        │   └── ...
        ├── ios/
        │   └── ...
        ├── .env.dev
        ├── .env.stage
        ├── .env.prod
        ├── package.json
        └── app.json

Next Steps After Generation

For Flutter Projects

  1. Navigate to the project directory:

    cd output/flutter/project_name
  2. Install dependencies:

    flutter pub get
  3. Run the app:

    # Development flavor
    flutter run --flavor dev -t lib/main_dev.dart
    
    # Staging flavor
    flutter run --flavor stage -t lib/main_stage.dart
    
    # Production flavor
    flutter run --flavor prod -t lib/main_prod.dart
  4. Build for release:

    flutter build apk --flavor prod -t lib/main_prod.dart
    flutter build ios --flavor prod -t lib/main_prod.dart

For React Native Projects

  1. Navigate to the project directory:

    cd output/rn/project_name
  2. Install dependencies:

    npm install
    # or
    yarn install
  3. Run the app:

    # Android - Development
    npx react-native run-android --mode=developmentdebug
    
    # Android - Staging
    npx react-native run-android --mode=stagedebug
    
    # Android - Production
    npx react-native run-android --mode=productionrelease
    
    # iOS - Development
    npx react-native run-ios --scheme=project_name-dev
    
    # iOS - Staging
    npx react-native run-ios --scheme=project_name-stage
    
    # iOS - Production
    npx react-native run-ios --scheme=project_name-prod
  4. Build for release:

    # Android
    cd android && ./gradlew assembleProductionRelease
    
    # iOS
    # Use Xcode to build and archive

CI/CD Integration

This tool is designed to work seamlessly in CI/CD pipelines. Here's how to integrate it:

GitHub Actions Example

name: Generate Mobile Apps

on:
  workflow_dispatch:
    inputs:
      project_name:
        description: 'Project name'
        required: true

jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Generate Flutter App
        env:
          GIT_TOKEN: ${{ secrets.BITBUCKET_APP_PASSWORD }}
          FLUTTER_PROD_KEYSTORE_PASSWORD: ${{ secrets.FLUTTER_KEYSTORE_PASSWORD }}
        run: |
          node setup-app.js --config config.json
      
      - name: Upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: generated-apps
          path: output/

GitLab CI Example

generate_apps:
  stage: build
  image: node:18
  before_script:
    - npm install -g git
  script:
    - node setup-app.js --config config.json
  artifacts:
    paths:
      - output/
    expire_in: 1 week
  only:
    - main

Jenkins Pipeline Example

pipeline {
    agent any
    
    environment {
        GIT_TOKEN = credentials('bitbucket-app-password')
        KEYSTORE_PASSWORD = credentials('keystore-password')
    }
    
    stages {
        stage('Generate Apps') {
            steps {
                sh 'node setup-app.js --config config.json'
            }
        }
        
        stage('Archive') {
            steps {
                archiveArtifacts 'output/**'
            }
        }
    }
}

Best Practices for CI/CD

  • Set all sensitive values as environment variables or secrets
  • Use --dry-run in a validation stage before actual generation
  • Cache the tool repository to speed up builds
  • Archive generated projects as build artifacts
  • Run generation in isolated containers/environments
  • Validate configuration files before running the tool

License

This tool is provided as-is for generating mobile applications from base architectures.

About

Deterministic Flutter and React Native mobile app generator that turns boilerplate into versioned infrastructure.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors