Code Generation

Transform your DSL models into working applications. This guide explains how Mosaic Builder generates production-ready code from conversational specifications.

Generation Pipeline

graph TD
    A[Complete DSL] --> B[Validation]
    B --> C[Template Selection]
    C --> D[Code Generation]
    D --> E[File Creation]
    E --> F[Post-Processing]
    F --> G[Ready to Deploy]

What Can Be Generated?

Database Layer

  • Prisma Schemas - Type-safe ORM definitions
  • Drizzle Schemas - SQL-like ORM schemas
  • Raw SQL - Migration files and DDL
  • Seed Data - Sample data for development
  • Backend Code

  • API Routes - RESTful or GraphQL endpoints
  • Authentication - Login, registration, sessions
  • Authorization - Role-based access control
  • Business Logic - Service layer functions
  • Validation - Input validation schemas
  • Frontend Components

  • React Components - UI components with TypeScript
  • Forms - Create/edit forms with validation
  • Tables - Data grids with sorting/filtering
  • Pages - Complete page layouts
  • Hooks - Custom React hooks for data
  • Infrastructure

  • Docker Files - Container configuration
  • CI/CD Pipelines - GitHub Actions workflows
  • Environment Config - .env templates
  • Deployment Scripts - Vercel, Railway, etc.
  • Generation Process

    Step 1: Readiness Check

    function canGenerate(dsl: DSLContext): boolean {
      return (
        dsl.readiness >= 75 &&
        Object.keys(dsl.entities).length > 0 &&
        dsl.phase === 'confirming' || dsl.phase === 'building'
      )
    }

    Step 2: Configuration

    interface GenerationConfig {
      database: {
        target: 'prisma' | 'drizzle' | 'sql'
        provider: 'postgresql' | 'mysql' | 'sqlite'
        includeSeeds: boolean
      }
      backend: {
        framework: 'nextjs' | 'express' | 'fastify'
        includeAuth: boolean
        includeTests: boolean
      }
      frontend: {
        framework: 'react' | 'vue' | 'svelte'
        styling: 'tailwind' | 'css' | 'styled-components'
        includeComponents: boolean
      }
    }

    Step 3: Template Processing

    // Templates use handlebars-style placeholders
    const template = `
    model {{entityName}} {
      id String @id @default(uuid())
      {{#each fields}}
      {{name}} {{type}}{{#if required}} {{/if}}{{#if unique}} @unique{{/if}}
      {{/each}}
      createdAt DateTime @default(now())
    }
    `

    Code Examples

    Generated Prisma Schema

    From conversation about a blog:
    // Generated from DSL
    generator client {
      provider = "prisma-client-js"
    }
    
    datasource db {
      provider = "postgresql"
      url      = env("DATABASE_URL")
    }
    
    model User {
      id        String   @id @default(uuid())
      email     String   @unique
      password  String
      name      String
      role      Role     @default(AUTHOR)
      createdAt DateTime @default(now())
      updatedAt DateTime @updatedAt
      
      posts     Post[]
      comments  Comment[]
    }
    
    model Post {
      id          String    @id @default(uuid())
      title       String
      slug        String    @unique
      content     String    @db.Text
      excerpt     String?
      status      PostStatus @default(DRAFT)
      publishedAt DateTime?
      authorId    String
      author      User      @relation(fields: [authorId], references: [id])
      createdAt   DateTime  @default(now())
      updatedAt   DateTime  @updatedAt
      
      comments    Comment[]
      tags        Tag[]
      
      @@index([status, publishedAt])
      @@index([authorId])
    }
    
    enum Role {
      ADMIN
      AUTHOR
      READER
    }
    
    enum PostStatus {
      DRAFT
      PUBLISHED
      ARCHIVED
    }

    Generated API Route

    // app/api/posts/route.ts
    import { NextRequest, NextResponse } from 'next/server'
    import { prisma } from '@/lib/prisma'
    import { z } from 'zod'
    import { requireAuth } from '@/lib/auth'
    
    // Validation schema
    const CreatePostSchema = z.object({
      title: z.string().min(1).max(200),
      content: z.string().min(1),
      status: z.enum(['DRAFT', 'PUBLISHED']),
      tags: z.array(z.string()).optional()
    })
    
    export async function GET(request: NextRequest) {
      const { searchParams } = new URL(request.url)
      const status = searchParams.get('status')
      
      const posts = await prisma.post.findMany({
        where: status ? { status } : undefined,
        include: {
          author: {
            select: { name: true, email: true }
          },
          _count: {
            select: { comments: true }
          }
        },
        orderBy: { createdAt: 'desc' }
      })
      
      return NextResponse.json(posts)
    }
    
    export async function POST(request: NextRequest) {
      const user = await requireAuth(request)
      if (!user) {
        return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
      }
      
      const body = await request.json()
      const validation = CreatePostSchema.safeParse(body)
      
      if (!validation.success) {
        return NextResponse.json(
          { error: validation.error.errors },
          { status: 400 }
        )
      }
      
      const post = await prisma.post.create({
        data: {
          ...validation.data,
          authorId: user.id,
          slug: generateSlug(validation.data.title)
        }
      })
      
      return NextResponse.json(post, { status: 201 })
    }

    Generated React Component

    // components/posts/PostForm.tsx
    'use client'
    
    import { useState } from 'react'
    import { useRouter } from 'next/navigation'
    import { Button } from '@/components/ui/button'
    import { Input } from '@/components/ui/input'
    import { Textarea } from '@/components/ui/textarea'
    import { Select } from '@/components/ui/select'
    
    interface PostFormProps {
      post?: {
        id: string
        title: string
        content: string
        status: 'DRAFT' | 'PUBLISHED'
      }
    }
    
    export function PostForm({ post }: PostFormProps) {
      const router = useRouter()
      const [loading, setLoading] = useState(false)
      const [formData, setFormData] = useState({
        title: post?.title || '',
        content: post?.content || '',
        status: post?.status || 'DRAFT'
      })
      
      const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault()
        setLoading(true)
        
        const method = post ? 'PUT' : 'POST'
        const url = post ? `/api/posts/${post.id}` : '/api/posts'
        
        const response = await fetch(url, {
          method,
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(formData)
        })
        
        if (response.ok) {
          router.push('/posts')
          router.refresh()
        }
        setLoading(false)
      }
      
      return (
        <form onSubmit={handleSubmit} className="space-y-4">
          <div>
            <label htmlFor="title">Title</label>
            <Input
              id="title"
              value={formData.title}
              onChange={(e) => setFormData({ ...formData, title: e.target.value })}
              required
              disabled={loading}
            />
          </div>
          
          <div>
            <label htmlFor="content">Content</label>
            <Textarea
              id="content"
              value={formData.content}
              onChange={(e) => setFormData({ ...formData, content: e.target.value })}
              required
              disabled={loading}
              rows={10}
            />
          </div>
          
          <div>
            <label htmlFor="status">Status</label>
            <Select
              id="status"
              value={formData.status}
              onChange={(e) => setFormData({ ...formData, status: e.target.value })}
              disabled={loading}
            >
              <option value="DRAFT">Draft</option>
              <option value="PUBLISHED">Published</option>
            </Select>
          </div>
          
          <Button type="submit" disabled={loading}>
            {loading ? 'Saving...' : post ? 'Update Post' : 'Create Post'}
          </Button>
        </form>
      )
    }

    Generation Strategies

    Progressive Generation

    Start with core functionality, add features incrementally:
  • Phase 1: Database schema only
  • Phase 2: Basic CRUD APIs
  • Phase 3: Authentication
  • Phase 4: UI components
  • Phase 5: Advanced features
  • Template-Based Generation

    Use pre-built templates for common patterns:
    const templates = {
      'blog': BlogTemplate,
      'ecommerce': EcommerceTemplate,
      'saas': SaaSTemplate,
      'crm': CRMTemplate
    }

    AI-Powered Generation

    LLM generates custom code based on specific requirements:
    async function generateCustomCode(dsl: DSLContext) {
      const prompt = `
        Generate a Next.js API route for the following entity:
        ${JSON.stringify(dsl.entities.Task)}
        
        Include:
        - Input validation
        - Error handling
        - Authentication checks
        - Proper TypeScript types
      `
      
      return await llm.generate(prompt)
    }

    Quality Assurance

    Validation Before Generation

    function validateDSL(dsl: DSLContext): ValidationResult {
      const errors = []
      
      // Check entities have required fields
      for (const entity of Object.values(dsl.entities)) {
        if (!entity.fields.id) {
          errors.push(`${entity.name} missing ID field`)
        }
      }
      
      // Check relationships are valid
    for (const rel of Object.values(dsl.relationships)) {
        if (!dsl.entities[rel.from] || !dsl.entities[rel.to]) {
          errors.push(`Invalid relationship: ${rel.from} -> ${rel.to}`)
        }
      }
      
      return { valid: errors.length === 0, errors }
    }

    Generated Code Features

  • Type Safety - Full TypeScript support
  • Validation - Input validation with Zod
  • Error Handling - Proper error responses
  • Security - Authentication and authorization
  • Performance - Optimized queries and caching
  • Documentation - JSDoc comments
  • Customization Options

    Code Style Preferences

    interface StylePreferences {
      indentation: 'spaces' | 'tabs'
      indentSize: 2 | 4
      quotes: 'single' | 'double'
      semicolons: boolean
      trailingComma: 'none' | 'es5' | 'all'
    }

    Framework Selection

    interface FrameworkConfig {
      frontend: {
        react: { version: '18' }
        nextjs: { version: '14', appRouter: true }
        styling: { tailwind: true, cssModules: false }
      }
      backend: {
        orm: 'prisma' | 'drizzle' | 'typeorm'
        validation: 'zod' | 'joi' | 'yup'
        auth: 'next-auth' | 'clerk' | 'custom'
      }
    }

    Custom Templates

    // Register custom generation template
    registerTemplate('myapp', {
      entity: (entity) => `
        // Custom entity template
        export class ${entity.name} {
          ${generateFields(entity.fields)}
        }
      `,
      api: (entity) => `
        // Custom API template
        export const ${entity.name}API = {
          ${generateMethods(entity)}
        }
      `
    })

    Generation Output

    File Structure

    generated/
    ├── prisma/
    │   ├── schema.prisma
    │   └── migrations/
    │       └── 001_initial/
    │           └── migration.sql
    ├── app/
    │   ├── api/
    │   │   ├── posts/
    │   │   │   └── route.ts
    │   │   └── auth/
    │   │       └── [...nextauth]/
    │   │           └── route.ts
    │   └── (app)/
    │       ├── posts/
    │       │   ├── page.tsx
    │       │   ├── [id]/
    │       │   │   └── page.tsx
    │       │   └── new/
    │       │       └── page.tsx
    ├── components/
    │   ├── posts/
    │   │   ├── PostList.tsx
    │   │   ├── PostForm.tsx
    │   │   └── PostCard.tsx
    │   └── ui/
    │       └── [generated components]
    └── lib/
        ├── prisma.ts
        ├── auth.ts
        └── validations/
            └── post.ts

    Download Options

  • ZIP Archive - Complete project download
  • Individual Files - Select specific files
  • Git Repository - Push to GitHub
  • Copy to Clipboard - For quick integration
  • Best Practices

    1. Review Before Using

    Always review generated code:
  • • Check business logic accuracy
  • • Verify security implementations
  • • Ensure performance optimizations
  • • Validate data structures
  • 2. Incremental Integration

    Don't replace everything at once:
  • Generate schema first
  • Test with migrations
  • Add API routes
  • Integrate UI components
  • Deploy incrementally
  • 3. Customization

    Generated code is a starting point:
  • • Modify to fit your style
  • • Add custom business logic
  • • Enhance with additional features
  • • Optimize for your use case
  • Troubleshooting

    Generation Failed

  • • Check DSL readiness (>75%)
  • • Ensure all entities have fields
  • • Verify relationships are valid
  • • Check for circular dependencies
  • Code Doesn't Compile

  • • Verify package.json dependencies
  • • Run pnpm install after generation
  • • Check TypeScript configuration
  • • Ensure database is configured
  • Missing Features

  • • Continue conversation to add features
  • • Manually enhance generated code
  • • Use custom templates for specific needs
  • Advanced Features

    Multi-Stage Generation

    // Generate in stages for complex apps
    const stages = [
      { name: 'database', readiness: 75 },
      { name: 'api', readiness: 85 },
      { name: 'ui', readiness: 90 },
      { name: 'tests', readiness: 95 }
    ]

    Merge with Existing Code

    // Intelligently merge with existing codebase
    const mergeStrategy = {
      mode: 'preserve', // Don't overwrite existing
      conflicts: 'prompt', // Ask user on conflicts
      backup: true // Create backups
    }

    Generation Hooks

    // Run custom logic during generation
    onBeforeGenerate((dsl) => {
      // Validate or modify DSL
    })
    
    onAfterGenerate((files) => {
      // Post-process files
      // Run formatters
      // Add custom files
    })

    Related Documentation

  • DSL Extraction - How structure is extracted
  • Entity Modeling - Design better models
  • First Conversation - See generation in action
  • Deployment Guide - Deploy generated code