Architecture
Generators

Generators

Framework-specific project generators that implement the core logic for creating React applications with different frameworks and configurations.

๐Ÿ—๏ธ Architecture Overview

React Kickstart uses the Template Method Pattern to provide a consistent generation process while allowing framework-specific customization.


๐Ÿ“ Structure

src/generators/
โ”œโ”€โ”€ base-generator.js           # Abstract base class
โ”œโ”€โ”€ frameworks/
โ”‚   โ”œโ”€โ”€ vite/
โ”‚   โ”‚   โ””โ”€โ”€ vite-generator.js   # Vite-specific implementation
โ”‚   โ””โ”€โ”€ nextjs/
โ”‚       โ””โ”€โ”€ nextjs-generator.js # Next.js-specific implementation
โ”œโ”€โ”€ content/                    # Content generation strategies
โ””โ”€โ”€ index.js                   # Generator selection logic

๐ŸŽฏ Template Method Pattern

The BaseGenerator defines the generation sequence, while concrete generators implement framework-specific details:

// BaseGenerator - Template Method Pattern
class BaseGenerator {
  async generate(projectPath, projectName, userChoices) {
    try {
      // 1. Create package.json with dependencies and scripts
      await this.createPackageConfiguration(projectPath, projectName, userChoices)
      
      // 2. Create framework-specific configuration files
      await this.createFrameworkConfiguration(projectPath, userChoices)
      
      // 3. Create core project files (HTML, entry points, App component)
      await this.createProjectFiles(projectPath, projectName, userChoices)
      
      // 4. Create framework-specific files and structure
      await this.createFrameworkSpecificFiles(projectPath, userChoices)
      
      UI_UTILS.success('Project structure created successfully')
    } catch (error) {
      throw new Error(`Generation failed: ${error.message}`)
    }
  }
  
  // Abstract methods - must be implemented by concrete generators
  async createFrameworkConfiguration(projectPath, userChoices) {
    throw new Error('Must implement createFrameworkConfiguration')
  }
  
  async createFrameworkSpecificFiles(projectPath, userChoices) {
    throw new Error('Must implement createFrameworkSpecificFiles')
  }
}

๐Ÿ”„ Generation Process

Generator Selection

The appropriate generator is selected based on the user's framework choice in src/generators/index.js:

function selectGenerator(framework) {
  switch (framework) {
    case "vite":
      return new ViteGenerator();
    case "nextjs":
      return new NextjsGenerator();
    default:
      throw new Error(`Unsupported framework: ${framework}`);
  }
}

Package Configuration

All generators create a package.json with framework-appropriate dependencies and scripts:

await this.createPackageConfiguration(projectPath, projectName, userChoices);
// Results in package.json with correct deps, scripts, and metadata

Framework Configuration

Each generator creates framework-specific configuration files:

  • Vite: vite.config.js/ts, index.html
  • Next.js: next.config.js, no HTML needed

Project Files

Core project files are created using the feature system:

await this.createProjectFiles(projectPath, projectName, userChoices);
// Creates src/App.tsx, entry points, etc.

Framework-Specific Files

Additional files and directory structures specific to each framework:

  • Vite: src/main.tsx, public assets, Vite-specific structure
  • Next.js: App Router or Pages Router structure, Next.js-specific files

๐ŸŽจ Content Generation

Generators use Content Generation Strategies to create appropriate code for different frameworks and routing configurations:

// Vite App.tsx with React Router
import React from 'react'
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Home from './pages/Home'
import About from './pages/About'
import './App.css'
 
function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <nav>
          <Link to="/">Home</Link>
          <Link to="/about">About</Link>
        </nav>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
        </Routes>
      </div>
    </BrowserRouter>
  )
}
 
export default App

๐Ÿ”ง Feature Integration

Generators coordinate with the Feature System to integrate selected technologies:

// Example: Integrating Redux with Vite
class ViteGenerator extends BaseGenerator {
  async createFrameworkSpecificFiles(projectPath, userChoices) {
    // Base file creation
    await this.createEntryFile(projectPath, userChoices);
 
    // Feature integration
    if (userChoices.state === "redux") {
      const reduxSetup = new ReduxSetup();
      await reduxSetup.integrate(projectPath, userChoices);
    }
 
    if (userChoices.styling === "tailwind") {
      const tailwindSetup = new TailwindSetup();
      await tailwindSetup.integrate(projectPath, userChoices, "vite");
    }
  }
}

๐Ÿงช Testing Integration

Generators ensure proper testing setup based on framework and user choices:

Framework-Specific Testing: Vite projects default to Vitest for optimal performance, while Next.js projects can use either Jest or Vitest.

// Testing configuration in generators
if (userChoices.testing === "vitest") {
  await configBuilder.generateVitestConfig(projectPath, userChoices);
} else if (userChoices.testing === "jest") {
  await configBuilder.generateJestConfig(projectPath, userChoices);
 
  // Special handling for Jest + Vite
  if (framework === "vite") {
    await this.createBabelConfig(projectPath); // Enable JSX transforms
  }
}

๐Ÿ”Œ Extension Points

Generators provide clear extension points for adding new frameworks:

Create Generator Class

Extend BaseGenerator and implement required methods:

class NewFrameworkGenerator extends BaseGenerator {
  async createFrameworkConfiguration(projectPath, userChoices) {
    // Framework-specific config creation
  }
 
  async createFrameworkSpecificFiles(projectPath, userChoices) {
    // Framework-specific file structure
  }
}

Register Generator

Add to the selection logic in src/generators/index.js:

case 'new-framework':
  return new NewFrameworkGenerator()

Update Dependencies

Add framework dependencies in src/builders/dependencies.js

Add to Prompts

Include in framework selection prompts


๐Ÿ› Error Handling

Generators include comprehensive error handling and cleanup:

class BaseGenerator {
  async generate(projectPath, projectName, userChoices) {
    try {
      await this.executeGeneration(projectPath, projectName, userChoices);
    } catch (error) {
      // Clean up partially created project
      await this.cleanup(projectPath);
 
      // Provide helpful error message
      throw new GenerationError(
        `Failed to generate ${userChoices.framework} project: ${error.message}`,
        error,
        { projectPath, framework: userChoices.framework }
      );
    }
  }
}

๐Ÿ“š Next Steps

Explore Related Systems:

Extend React Kickstart:

Want to add a new framework? The generator system is designed for easy extension. Follow the Template Method Pattern and implement the required methods.