As developers, we love building features.
What we don't enjoy is spending hours setting up the same project for the tenth time.
At my company, every new React Native project followed a familiar pattern:
- Create the application
- Configure TypeScript
- Install dependencies
- Set up Firebase
- Configure environment variables
- Add Fastlane
- Configure CI/CD
- Create the project structure
- Add shared utilities and configurations
None of these tasks were difficult, but they were repetitive.
After creating multiple applications and following the same setup checklist over and over, I started asking myself a simple question:
Why are we manually doing work that can be automated?
That question led me to build CAM (Custom App Manager) — a CLI tool that can create and configure a production-ready mobile application with a single command.
cam create-app MyApp
In this article, I'll walk through how I built it and the tools that made it possible.
The Problem
Every team eventually develops its own preferred architecture and setup process.
The challenge is ensuring every developer follows it consistently.
For us, creating a new application meant:
npx react-native init MyApp
# Install dependencies
npm install @react-navigation/native
npm install axios
npm install react-query
# Configure Firebase
# Create environment files
# Setup Fastlane
# Configure CI/CD
# Create folder structure
Even with documentation, the process was:
- Time-consuming
- Error-prone
- Difficult for new developers
- Inconsistent across projects
I wanted a solution that would convert our setup documentation into executable code.
Introducing CAM (Custom App Manager)
CAM is an internal CLI tool that automates mobile app creation and configuration.
Instead of spending hours setting up a project, developers simply run:
cam create-app MyApp
CAM then:
- Creates the project
- Installs dependencies
- Generates folder structures
- Configures Firebase
- Creates environment files
- Adds Fastlane configuration
- Applies company standards
- Sets up CI/CD templates
The goal was simple:
Move developers from setup mode to feature development as quickly as possible.
Building The CLI
Command Parsing With Commander.js
The first requirement was creating custom commands.
I used Commander.js to build the command-line interface.
import { Command } from 'commander';
const program = new Command();
program
.command('create-app <name>')
.description('Create a new application')
.action((name) => {
console.log(`Creating ${name}`);
});
program.parse();
This allowed CAM to support commands such as:
cam create-app MyApp
cam upgrade
cam configure-firebase
cam setup-fastlane
Commander handles argument parsing, validation, help menus, and command organization.
Interactive Setup With Inquirer
Not every application requires the same configuration.
To make CAM flexible, I used Inquirer.js for interactive prompts.
import inquirer from 'inquirer';
const answers = await inquirer.prompt([
{
type: 'confirm',
name: 'firebase',
message: 'Enable Firebase?'
}
]);
This allows developers to customize their projects during creation.
Examples:
- Enable Firebase?
- Configure Analytics?
- Include Push Notifications?
- Setup Fastlane?
Based on the answers, CAM adjusts the generated project.
File Management With fs-extra
A large portion of CAM's functionality involves generating files and copying templates.
For this, I used fs-extra.
import fs from 'fs-extra';
await fs.copy(
'./templates/react-native-base',
'./MyApp'
);
This library simplifies:
- Copying directories
- Creating folders
- Updating configuration files
- Managing templates
Running Shell Commands With child_process
Project setup often requires executing external commands.
Examples:
npm install
pod install
fastlane init
Node's child_process module allows CAM to execute these commands programmatically.
import { execSync } from 'child_process';
execSync(
'npm install',
{ stdio: 'inherit' }
);
This became the orchestration layer that ties everything together.
Template-Based Project Generation
One of the best decisions I made was using templates instead of generating files from scratch.
The CLI maintains a collection of project templates:
templates/
├── react-native-base/
├── firebase-enabled/
├── analytics-enabled/
├── fastlane-config/
└── enterprise-template/
When a developer runs:
cam create-app MyApp
CAM selects the appropriate templates and customizes them with project-specific values.
This approach makes maintenance significantly easier because templates can evolve independently.
Automating Firebase Configuration
Firebase setup was one of the most repetitive parts of every project.
CAM automates:
- Package installation
- Environment setup
- Firebase initialization
- Boilerplate service creation
- Configuration file placement
Instead of following lengthy setup documentation, developers answer a few prompts and continue building features.
Environment Management
Almost every project needs multiple environments.
Typically:
.env.dev
.env.qa
.env.stage
.env.prod
CAM generates these automatically and injects the required configuration values.
This reduces setup mistakes and keeps environments consistent across applications.
Fastlane Integration
Another recurring task was configuring deployment pipelines.
CAM can generate Fastlane configurations for:
- Android builds
- iOS builds
- Beta deployments
- Store releases
Instead of manually creating lanes for every new project, developers start with a standardized configuration.
CI/CD Automation
Since our projects use automated pipelines, CAM also generates CI/CD templates.
This includes:
- Build workflows
- Environment configuration
- Test execution steps
- Deployment templates
A newly created project is immediately ready for automation.
Standardizing Architecture
The original goal was saving time.
The biggest benefit turned out to be consistency.
Every generated project follows the same structure:
src/
├── components/
├── screens/
├── hooks/
├── services/
├── navigation/
├── utils/
├── assets/
└── constants/
Benefits include:
- Easier onboarding
- Faster code reviews
- Predictable project organization
- Reduced technical debt
Developers no longer debate where code should live because every project starts from the same foundation.
Lessons Learned
1. Repetition Is A Signal
If you find yourself following the same setup checklist repeatedly, it's probably a candidate for automation.
2. Templates Scale Better Than Generators
Copying and customizing templates is often easier to maintain than generating every file programmatically.
3. Consistency Is More Valuable Than Speed
The time savings were great.
The real value came from ensuring every project followed the same standards from day one.
4. Start Small
The first version of CAM automated only a handful of tasks.
Over time it evolved to include:
- Project creation
- Firebase setup
- Environment management
- Fastlane integration
- CI/CD templates
- Dependency installation
Automation compounds over time.
What's Next?
Future improvements include:
- Automatic Firebase project provisioning
- Store configuration automation
- Dependency upgrade management
- Automated test setup
- Playwright and E2E testing configuration
The long-term goal is to make project creation nearly effortless.
Final Thoughts
CAM started as a side project to eliminate repetitive setup work.
It eventually became a way to standardize how mobile applications are built across the organization.
What once required dozens of commands, configuration steps, and setup guides can now be accomplished with:
cam create-app MyApp
The result is faster onboarding, fewer setup mistakes, and a more consistent development experience for everyone involved.
If your team keeps rebuilding the same foundation for every project, consider investing time in a custom CLI. It might be one of the highest-leverage tools you build.
Top comments (0)