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
Backend Code
Frontend Components
Infrastructure
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: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
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
Best Practices
1. Review Before Using
Always review generated code:2. Incremental Integration
Don't replace everything at once:3. Customization
Generated code is a starting point:Troubleshooting
Generation Failed
Code Doesn't Compile
pnpm install
after generationMissing Features
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
})