Skip to content

Essay ·

Proto Artisan: AI Code Prototyper

Proto Artisan transforms AI-generated code into production-ready applications using LEGO Builder principles and automatic pattern detection.

Proto Artisan is an intelligent code analyzer that transforms AI-generated prototypes into production-ready applications by automatically detecting patterns, extracting reusable components, and reorganizing code according to LEGO Builder principles.

This case study explores how we built a tool that bridges the gap between rapid AI prototyping and maintainable software architecture.

The Problem: AI-Generated Technical Debt

AI coding assistants like Claude, ChatGPT, and GitHub Copilot have revolutionized prototyping. You can describe a feature and get working code in minutes. But there's a catch:

  • Monolithic Functions: AI tends to generate everything in a single function (200+ lines)
  • Inline Duplication: Similar logic repeated across different parts of the codebase
  • No Architectural Patterns: Code that works but doesn't scale or maintain well
  • Testing Difficulty: Tightly coupled code that's nearly impossible to test

Developers faced a choice: spend hours manually refactoring AI code, or accept technical debt from day one. Proto Artisan offers a third option: automated refactoring guided by LEGO Builder principles.

The Solution: Intelligent Pattern Detection

Architecture Overview

Proto Artisan consists of three main systems:

// System Architecture
src/
├── analyzers/           // Detect patterns and duplications
├── extractors/          // Pull out reusable blocks
├── generators/          // Create modular file structure
├── validators/          // Ensure LEGO compliance
└── orchestrators/       // Coordinate the refactoring process

Pattern Detection Engine

The core of Proto Artisan is its pattern detection system:

// analyzers/pattern-detector.js (29 lines)
export function detectPatterns(codeString) {
    const ast = parseToAST(codeString);
    const patterns = {
        utilities: findPureFunctions(ast),
        builders: findObjectConstructors(ast),
        guards: findValidators(ast),
        processors: findBusinessLogic(ast),
        duplicates: findDuplicateLogic(ast)
    };

    return patterns;
}

// analyzers/duplicate-finder.js (27 lines)
export function findDuplicateLogic(ast) {
    const functionBodies = extractFunctionBodies(ast);
    const signatures = functionBodies.map(computeSignature);

    const duplicates = [];
    for (let i = 0; i < signatures.length; i++) {
        for (let j = i + 1; j < signatures.length; j++) {
            if (similarityScore(signatures[i], signatures[j]) > 0.8) {
                duplicates.push({
                    first: functionBodies[i],
                    second: functionBodies[j],
                    similarity: similarityScore(signatures[i], signatures[j])
                });
            }
        }
    }

    return duplicates;
}

Automatic Block Extraction

Once patterns are detected, Proto Artisan extracts them into proper LEGO blocks:

// extractors/utility-extractor.js (28 lines)
export function extractUtilities(patterns) {
    const utilities = [];

    patterns.utilities.forEach(func => {
        const utility = {
            name: generateDescriptiveName(func),
            code: func.code,
            inputs: func.parameters,
            output: func.returnType,
            category: categorizeUtility(func)
        };

        // Ensure LEGO compliance
        if (utility.code.split('\n').length > 30) {
            utility.needsRefactoring = true;
            utility.suggestions = suggestBreakdown(utility.code);
        }

        utilities.push(utility);
    });

    return utilities;
}

Real-World Example: Refactoring a Monolith

Before: AI-Generated Monolith (127 lines)

// AI generated this as a single function
async function handleUserRegistration(req, res) {
    // Validation (15 lines)
    const email = req.body.email;
    if (!email || !email.includes('@')) {
        return res.status(400).json({ error: 'Invalid email' });
    }
    // ... more validation

    // Database operations (25 lines)
    const userExists = await db.query('SELECT * FROM users WHERE email = $1', [email]);
    if (userExists.rows.length > 0) {
        return res.status(409).json({ error: 'User exists' });
    }
    // ... more database code

    // Password hashing (12 lines)
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(req.body.password, salt);
    // ... more hashing logic

    // Email sending (20 lines)
    const transporter = nodemailer.createTransport({ /* config */ });
    const mailOptions = { /* options */ };
    await transporter.sendMail(mailOptions);
    // ... more email code

    // Token generation (15 lines)
    const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET);
    // ... more token logic

    // Response handling (10 lines)
    res.json({ success: true, token, user });
}

After: Proto Artisan Refactoring

// utilities/email-validator.js (8 lines)
export function isValidEmail(email) {
    return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}

// utilities/password-hasher.js (12 lines)
export async function hashPassword(password) {
    const salt = await bcrypt.genSalt(10);
    return bcrypt.hash(password, salt);
}

// guards/user-existence-guard.js (15 lines)
export async function requireNewUser(email) {
    const existing = await getUserByEmail(email);
    if (existing) {
        throw new Error('User already exists');
    }
}

// builders/user-builder.js (18 lines)
export function buildUser(userData, hashedPassword) {
    return {
        email: userData.email,
        password: hashedPassword,
        name: userData.name,
        createdAt: new Date()
    };
}

// bridges/email-bridge.js (22 lines)
export async function sendWelcomeEmail(email, name) {
    const transporter = createTransporter();
    const mailOptions = buildWelcomeEmail(email, name);
    await transporter.sendMail(mailOptions);
}

// utilities/token-generator.js (14 lines)
export function generateAuthToken(userId) {
    return jwt.sign(
        { userId },
        process.env.JWT_SECRET,
        { expiresIn: '7d' }
    );
}

// controllers/registration-controller.js (26 lines)
export async function handleUserRegistration(req, res) {
    try {
        const { email, password, name } = req.body;

        if (!isValidEmail(email)) {
            return res.status(400).json({ error: 'Invalid email' });
        }

        await requireNewUser(email);

        const hashedPassword = await hashPassword(password);
        const user = buildUser({ email, name }, hashedPassword);

        await saveUser(user);
        await sendWelcomeEmail(email, name);

        const token = generateAuthToken(user.id);

        res.json({ success: true, token, user });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
}

The Technical Stack

Core Technologies

  • Parser: Acorn.js for JavaScript AST generation
  • Analysis: Custom pattern matching algorithms
  • Similarity Detection: Levenshtein distance and structural hashing
  • Code Generation: Template-based file generation
  • UI: React with real-time diff visualization

Key Features

1. Smart Naming

Proto Artisan generates meaningful names based on function behavior:

// analyzers/name-generator.js (24 lines)
export function generateDescriptiveName(funcNode) {
    const verbs = extractVerbs(funcNode);
    const nouns = extractNouns(funcNode);

    if (funcNode.returnsPure) return `${verbs[0]}${capitalize(nouns[0])}`;
    if (funcNode.buildsObject) return `build${capitalize(nouns[0])}`;
    if (funcNode.validates) return `validate${capitalize(nouns[0])}`;
    if (funcNode.checks) return `is${capitalize(nouns[0])}Valid`;

    return `${verbs[0]}${capitalize(nouns[0])}`;
}

2. LEGO Compliance Validation

Every extracted block is validated against LEGO Builder rules:

  • Maximum 30 lines of code
  • Single responsibility principle
  • Clear input/output contracts
  • No hidden dependencies
  • Maximum 3 functions per file

3. Visual Diff Comparison

Developers can see before/after comparisons with:

  • Line count reduction metrics
  • Duplication elimination stats
  • Test coverage improvements
  • File organization visualization

Results and Impact

Measurable Improvements

  • Code Reduction: Average 35% reduction in total lines (duplicate elimination)
  • Maintainability: Cyclomatic complexity reduced by 60%
  • Test Coverage: Testable blocks increased from 20% to 85%
  • Refactoring Time: 3-hour manual refactoring → 10-minute automated process

Developer Productivity

Teams using Proto Artisan report:

  • Faster onboarding (new developers understand modular code more quickly)
  • Confident AI usage (no fear of accumulating technical debt)
  • Faster debugging (small blocks are easier to trace)
  • Reusable components (extracted utilities used across projects)

Lessons Learned

1. AI Code Has Patterns

Despite different prompts, AI assistants generate similar patterns. These patterns are predictable and can be detected algorithmically.

2. Naming is Critical

Automatically generated names must be descriptive. Poor names defeat the purpose of modular code.

3. Developers Need Control

Proto Artisan suggests refactorings but lets developers approve or modify them. Full automation would miss context that humans understand.

4. LEGO Principles Scale

The same principles that make hand-written code maintainable also make AI-refactored code maintainable. The 30-line rule works whether a human or machine wrote the original code.

The Future of AI-Assisted Development

Proto Artisan represents a new paradigm: using AI to prototype rapidly, then using intelligent tooling to transform prototypes into production-quality architecture.

This workflow combines the best of both worlds:

  • Speed: AI generates working code in minutes
  • Quality: Automated refactoring ensures maintainability
  • Control: Developers review and approve all changes
  • Learning: Developers see how monoliths decompose into blocks

As AI coding assistants become more powerful, tools like Proto Artisan will become essential for maintaining code quality at the speed of AI generation.

← Back to Blog

Got a system that won't do what you need?

That's the whole job. Thirty minutes, free, and you'll leave knowing whether it's worth doing.