Development Automation

Automation & CLI Tools

Complete guide to CLI tools, automation scripts, and development utilities that streamline your NextReady development workflow.

Interactive setup
One-command deployment
Automated validation

Automation Tools

Interactive Setup CLI
Guided project initialization and configuration
  • Environment configuration wizard
  • Database setup automation
  • Service integration helpers
  • Validation and testing tools
Brand Customization
Automated branding and theme customization
  • Color scheme generation
  • Logo replacement system
  • Font family updates
  • Asset optimization pipeline
Database Management
Comprehensive database automation tools
  • Migration generation and deployment
  • Seeding with sample data
  • Backup and restore utilities
  • Connection testing and validation
Development Utilities
Tools to streamline development workflow
  • Code generation templates
  • Testing automation scripts
  • Build and deployment helpers
  • Performance monitoring tools

CLI Script Examples

Interactive Setup CLI
Comprehensive project setup with guided configuration
// scripts/setup.js - Interactive Setup CLI
const inquirer = require('inquirer');
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const chalk = require('chalk');

class NextReadySetup {
  constructor() {
    this.projectPath = process.cwd();
    this.envPath = path.join(this.projectPath, '.env.local');
    this.config = {};
  }

  async run() {
    console.log(chalk.blue.bold('šŸš€ NextReady Interactive Setup\n'));
    
    try {
      await this.welcomeMessage();
      await this.collectProjectInfo();
      await this.setupEnvironment();
      await this.setupDatabase();
      await this.setupServices();
      await this.runFinalSteps();
      
      console.log(chalk.green.bold('\nāœ… Setup completed successfully!'));
      console.log(chalk.cyan('Run npm run dev to start your application'));
    } catch (error) {
      console.error(chalk.red('Setup failed:'), error.message);
      process.exit(1);
    }
  }

  async welcomeMessage() {
    const { proceed } = await inquirer.prompt([
      {
        type: 'confirm',
        name: 'proceed',
        message: 'Welcome to NextReady! This will guide you through the setup process. Continue?',
        default: true
      }
    ]);

    if (!proceed) {
      console.log('Setup cancelled.');
      process.exit(0);
    }
  }

  async collectProjectInfo() {
    console.log(chalk.yellow('\nšŸ“‹ Project Information'));
    
    const answers = await inquirer.prompt([
      {
        type: 'input',
        name: 'projectName',
        message: 'What is your project name?',
        default: path.basename(this.projectPath),
        validate: (input) => input.trim() !== '' || 'Project name cannot be empty'
      },
      {
        type: 'input',
        name: 'description',
        message: 'Project description (optional):',
        default: 'A NextReady application'
      },
      {
        type: 'input',
        name: 'author',
        message: 'Author name:',
        default: 'Your Name'
      }
    ]);

    this.config.project = answers;
    await this.updatePackageJson();
  }

  async setupEnvironment() {
    console.log(chalk.yellow('\nšŸ”§ Environment Setup'));
    
    const answers = await inquirer.prompt([
      {
        type: 'input',
        name: 'appUrl',
        message: 'Application URL (for production):',
        default: 'https://your-domain.com',
        validate: (input) => {
          try {
            new URL(input);
            return true;
          } catch {
            return 'Please enter a valid URL';
          }
        }
      },
      {
        type: 'password',
        name: 'nextAuthSecret',
        message: 'NextAuth secret (press enter to generate):',
        mask: '*'
      }
    ]);

    // Generate secret if not provided
    if (!answers.nextAuthSecret) {
      answers.nextAuthSecret = this.generateSecret();
      console.log(chalk.green('Generated NextAuth secret automatically'));
    }

    this.config.env = answers;
  }

  async setupDatabase() {
    console.log(chalk.yellow('\nšŸ—„ļø  Database Configuration'));
    
    const { setupDb } = await inquirer.prompt([
      {
        type: 'confirm',
        name: 'setupDb',
        message: 'Would you like to set up the database now?',
        default: true
      }
    ]);

    if (!setupDb) {
      console.log(chalk.gray('Skipping database setup'));
      return;
    }

    const dbAnswers = await inquirer.prompt([
      {
        type: 'input',
        name: 'databaseUrl',
        message: 'Database URL (Neon PostgreSQL):',
        validate: (input) => {
          if (!input.trim()) return 'Database URL is required';
          if (!input.includes('postgresql://')) return 'Please enter a valid PostgreSQL URL';
          return true;
        }
      },
      {
        type: 'confirm',
        name: 'runMigrations',
        message: 'Run database migrations?',
        default: true
      },
      {
        type: 'confirm',
        name: 'seedData',
        message: 'Seed with sample data?',
        default: true
      }
    ]);

    this.config.database = dbAnswers;

    if (dbAnswers.runMigrations) {
      await this.runDatabaseMigrations();
    }

    if (dbAnswers.seedData) {
      await this.seedDatabase();
    }
  }

  async setupServices() {
    console.log(chalk.yellow('\nāš™ļø  External Services'));
    
    const services = await inquirer.prompt([
      {
        type: 'checkbox',
        name: 'selectedServices',
        message: 'Which services would you like to configure?',
        choices: [
          { name: 'File Storage (Vercel Blob)', value: 'blob' },
          { name: 'Email Service (Resend)', value: 'email' },
          { name: 'OAuth Providers', value: 'oauth' }
        ]
      }
    ]);

    for (const service of services.selectedServices) {
      await this.setupService(service);
    }
  }

  async setupService(service) {
    switch (service) {
      case 'blob':
        await this.setupVercelBlob();
        break;
      case 'email':
        await this.setupResend();
        break;
      case 'oauth':
        await this.setupOAuth();
        break;
    }
  }

  async setupVercelBlob() {
    const answers = await inquirer.prompt([
      {
        type: 'input',
        name: 'blobToken',
        message: 'Vercel Blob read-write token:',
        validate: (input) => input.trim() !== '' || 'Blob token is required'
      }
    ]);
    
    this.config.blob = answers;
    console.log(chalk.green('āœ… Vercel Blob configured'));
  }

  async setupResend() {
    const answers = await inquirer.prompt([
      {
        type: 'input',
        name: 'resendApiKey',
        message: 'Resend API key:',
        validate: (input) => input.trim() !== '' || 'Resend API key is required'
      },
      {
        type: 'input',
        name: 'fromEmail',
        message: 'From email address:',
        default: 'NextReady <noreply@your-domain.com>',
        validate: (input) => {
          const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
          return emailRegex.test(input.split('<')[1]?.replace('>', '') || input) || 'Please enter a valid email';
        }
      }
    ]);
    
    this.config.email = answers;
    console.log(chalk.green('āœ… Email service configured'));
  }

  async generateEnvFile() {
    const envContent = [
      '# Generated by NextReady Setup',
      `# Project: ${this.config.project.projectName}`,
      `# Generated: ${new Date().toISOString()}`,
      '',
      '# NextAuth Configuration',
      `NEXTAUTH_SECRET="${this.config.env.nextAuthSecret}"`,
      `NEXTAUTH_URL="${this.config.env.appUrl}"`,
      '',
      '# Database Configuration',
      `DATABASE_URL="${this.config.database?.databaseUrl || ''}"`,
      `DIRECT_URL="${this.config.database?.databaseUrl?.replace('?pgbouncer=true', '') || ''}"`,
      ''
    ];

    if (this.config.blob) {
      envContent.push('# File Storage');
      envContent.push(`BLOB_READ_WRITE_TOKEN="${this.config.blob.blobToken}"`);
      envContent.push('');
    }

    if (this.config.email) {
      envContent.push('# Email Service');
      envContent.push(`RESEND_API_KEY="${this.config.email.resendApiKey}"`);
      envContent.push(`EMAIL_FROM="${this.config.email.fromEmail}"`);
      envContent.push('');
    }

    fs.writeFileSync(this.envPath, envContent.join('\n'));
    console.log(chalk.green(`āœ… Environment file created: .env.local`));
  }

  async runFinalSteps() {
    console.log(chalk.yellow('\nšŸ Final Steps'));
    
    await this.generateEnvFile();
    
    const { runTests } = await inquirer.prompt([
      {
        type: 'confirm',
        name: 'runTests',
        message: 'Run configuration tests?',
        default: true
      }
    ]);

    if (runTests) {
      await this.validateConfiguration();
    }
  }

  generateSecret() {
    return require('crypto').randomBytes(32).toString('hex');
  }

  async runDatabaseMigrations() {
    try {
      console.log(chalk.blue('Running database migrations...'));
      execSync('npm run db:push', { stdio: 'inherit' });
      console.log(chalk.green('āœ… Database migrations completed'));
    } catch (error) {
      console.log(chalk.red('āŒ Migration failed'), error.message);
    }
  }

  async validateConfiguration() {
    console.log(chalk.blue('\nšŸ” Validating configuration...'));
    
    // Test database connection
    try {
      execSync('npm run db:test', { stdio: 'pipe' });
      console.log(chalk.green('āœ… Database connection successful'));
    } catch (error) {
      console.log(chalk.yellow('āš ļø  Database connection could not be verified'));
    }
    
    // Validate environment file
    if (fs.existsSync(this.envPath)) {
      console.log(chalk.green('āœ… Environment file created'));
    }
    
    console.log(chalk.green('āœ… Configuration validation completed'));
  }
}

if (require.main === module) {
  new NextReadySetup().run().catch(console.error);
}

module.exports = NextReadySetup;

Available Commands

Automation Commands
Ready-to-use commands for common development tasks
npm run setup

Interactive project setup and configuration

Complete project initialization

npm run brand

Brand customization tool

Update colors, fonts, and assets

npm run db:setup

Database setup with migrations and seeding

Initialize database from scratch

npm run validate

Validate project configuration

Check setup completeness and connectivity

npm run db:backup

Create database backup

Backup production data

npm run optimize

Optimize assets and performance

Pre-deployment optimization

Common Workflows

New Project Setup
Complete project initialization workflow
1
npm run setupInteractive configuration
2
npm run validateVerify setup
3
npm run devStart development
Production Deployment
Pre-deployment preparation workflow
1
npm run validateCheck configuration
2
npm run buildBuild application
3
npm run optimizeOptimize assets

Automation Best Practices

šŸ¤– Automation Ready!

Your automation toolkit is configured and ready to streamline your development workflow with powerful CLI tools.