Procedural Generation Workflows

Problem

Creating consistent, high-quality code and documentation manually is time-consuming and error-prone. Need a multi-tiered generation pipeline that scales from architectural decisions to implementation details.

Solution

Multi-layer generator architecture using specialized tools at each level:

┌─────────────────────────────────────────┐
│          ARCHITECT LAYER                │
│         (Yellicode, Hygen)              │
│    System-wide patterns & scaffolds     │
└───────────────┬─────────────────────────┘
                │
┌───────────────▼─────────────────────────┐
│           BUILDER LAYER                 │
│         (Plop.js, Cookiecutter)         │
│    Component/module generation          │
└───────────────┬─────────────────────────┘
                │
┌───────────────▼─────────────────────────┐
│         SPECIALIST LAYER                │
│         (Jinja2, Handlebars)            │
│    File-level templating                │
└─────────────────────────────────────────┘

Layer 1: Architect (Yellicode)

System-wide code generation from models:

// yellicode/model.ts
import { Model } from '@yellicode/elements';
 
const model: Model = {
  entities: [
    { name: 'User', fields: ['id', 'email', 'name'] },
    { name: 'Order', fields: ['id', 'userId', 'total'] },
  ],
  relationships: [{ from: 'User', to: 'Order', type: 'hasMany' }],
};

Layer 2: Builder (Plop.js)

Interactive component scaffolding:

// plopfile.js
module.exports = function (plop) {
  plop.setGenerator('component', {
    description: 'Create a React component',
    prompts: [{ type: 'input', name: 'name', message: 'Component name?' }],
    actions: [
      {
        type: 'add',
        path: 'src/components/{{pascalCase name}}/index.tsx',
        templateFile: 'plop-templates/component.hbs',
      },
      {
        type: 'add',
        path: 'src/components/{{pascalCase name}}/{{pascalCase name}}.test.tsx',
        templateFile: 'plop-templates/component.test.hbs',
      },
    ],
  });
};

Layer 3: Specialist (Jinja2)

File-level templating:

{# templates/api_endpoint.py.j2 #}
from fastapi import APIRouter
 
router = APIRouter()
 
@router.{{ method }}("/{{ path }}")
async def {{ function_name }}({% for param in params %}{{ param.name }}: {{ param.type }}{% if not loop.last %}, {% endif %}{% endfor %}):
    """{{ docstring }}"""
    {{ body | indent(4) }}

Usage

Integrated Pipeline

# 1. Architect: Generate system scaffolds
yellicode generate --model ./model.yml
 
# 2. Builder: Create components interactively
npx plop component UserProfile
 
# 3. Specialist: Fill in templates
python render_template.py --template api.j2 --data config.yml

Persona Vectors for Test Data

Generate realistic test data by defining personas:

personas:
  - name: 'Early Adopter'
    traits: { risk_tolerance: high, tech_savvy: high }
  - name: 'Cautious User'
    traits: { risk_tolerance: low, detail_oriented: high }

Trade-offs

When to Use

  • Consistent code structure across team
  • Boilerplate-heavy domains
  • Documentation generation
  • Test data creation
  • Infrastructure as Code

When NOT to Use

  • One-off scripts
  • Highly unique components
  • Rapidly changing requirements

Source

Extracted from procedural generation research for multi-project organization.