compose.json Specification

November 25, 2025 · View on GitHub

Version: 1.0.0

The compose.json file is the configuration file for Compose projects. It defines LLM settings, deployment targets, and build configuration.


Structure

{
  "name": "my-app",
  "version": "1.0.0",
  "description": "Project description",
  
  "llm": { ... },
  "targets": { ... },
  "global": { ... }
}

Required Fields

FieldTypeRequiredDescription
llmobjectYesLLM configuration
targetsobjectYesDeployment targets (at least one)

Minimum valid compose.json:

{
  "llm": {
    "provider": "gemini",
    "model": "gemini-2.5-flash",
    "apiKey": "${GEMINI_API_KEY}"
  },
  "targets": {
    "web": {
      "entry": "./app.compose",
      "framework": "nextjs",
      "language": "typescript",
      "output": "./generated/web"
    }
  }
}

LLM Configuration

Required fields:

{
  "llm": {
    "provider": "gemini",        // Required: "gemini" | "openai" | "anthropic"
    "model": "model-name",       // Required: Model identifier
    "apiKey": "${ENV_VAR}",      // Required: API key (use env vars)
    "temperature": 0.2,          // Optional: 0.0-1.0 (default: 0.2)
    "maxTokens": 8192            // Optional: Max response tokens (default: 8192)
  }
}

Supported Providers & Models

Gemini (Google):

{
  "provider": "gemini",
  "model": "gemini-2.5-flash",    // Fast, recommended
  "model": "gemini-1.5-pro",      // High quality
  "apiKey": "${GEMINI_API_KEY}"
}

OpenAI:

{
  "provider": "openai",
  "model": "gpt-4-turbo",
  "model": "gpt-4o",
  "apiKey": "${OPENAI_API_KEY}"
}

Anthropic:

{
  "provider": "anthropic",
  "model": "claude-3-5-sonnet",
  "apiKey": "${ANTHROPIC_API_KEY}"
}

Targets Configuration

At least one target is required.

Each target represents a deployment environment (web, API, mobile, etc.).

Target Structure

{
  "targets": {
    "web": {                          // Target name (user-defined)
      "entry": "./app.compose",       // Required: Entry point .compose file
      "framework": "nextjs",          // Required: Framework identifier
      "language": "typescript",       // Required: Output language
      "output": "./generated/web",    // Required: Output directory
      "dependencies": [...],          // Optional: Additional npm packages
      "assets": [...],                // Optional: Asset copying
      "extraRules": [...]             // Optional: LLM instructions
    }
  }
}

Note: The type field is automatically inferred from the framework (e.g., nextjsreact, expressnode). You can still specify it manually if needed.

Required Target Fields

FieldTypeRequiredDescription
entrystringYesPath to entry .compose file
languagestringYesOutput language
outputstringYesOutput directory path
frameworkstringNoFramework identifier (optional)
dependenciesstring[]NoAdditional npm packages
assets[from, to][]NoAsset copy mappings
extraRulesstring[]NoLLM instructions

Type Auto-Inference:

  • nextjs, vite-react, remixreact
  • express, fastify, nestjsnode
  • react-native, fluttermobile
  • vue, svelteweb

Framework Identifiers

Frontend:

  • nextjs - Next.js (React)
  • vite-react - Vite + React
  • remix - Remix
  • vue - Vue.js
  • svelte - Svelte

Backend:

  • express - Express.js
  • fastify - Fastify
  • nestjs - NestJS

Mobile:

  • react-native - React Native
  • flutter - Flutter

Other:

  • rust - Rust
  • go - Go
  • python - Python

Language Identifiers

Required values:

  • typescript
  • javascript
  • python
  • rust
  • go
  • dart (for Flutter)
  • swift (for iOS)
  • kotlin (for Android)

Optional Target Fields

Dependencies

Array of npm package names to install:

{
  "dependencies": [
    "react-query",
    "zustand",
    "@radix-ui/react-dialog"
  ]
}

Use for:

  • UI libraries
  • State management
  • Form validation
  • Date/time utilities

Assets

Array of [source, destination] pairs for copying static files:

{
  "assets": [
    ["assets/logo.svg", "public/logo.svg"],
    ["assets/favicon.ico", "public/favicon.ico"],
    ["assets/images", "public/images"]
  ]
}

Format: [from, to]

  • from (index 0): Source path (relative to project root)
  • to (index 1): Destination path (relative to target output)

Examples:

// Copy single file
["assets/logo.svg", "public/logo.svg"]

// Copy entire directory
["assets/images", "public/images"]

// Copy with different name
["assets/app-icon.png", "public/icon.png"]

Extra Rules

Array of additional LLM instructions specific to this target:

{
  "extraRules": [
    "Use React Server Components where possible",
    "Implement dark mode with next-themes",
    "All forms must use react-hook-form with zod validation",
    "Add proper ARIA labels for accessibility"
  ]
}

Use for:

  • Framework-specific patterns
  • Performance optimizations
  • Security requirements
  • Accessibility rules
  • Custom conventions

Global Configuration

Optional global settings:

{
  "global": {
    "packageManager": "npm",      // "npm" | "yarn" | "pnpm"
    "nodeVersion": "20",          // Node.js version
    "moduleSystem": "esm"         // "esm" | "commonjs"
  }
}

Complete Example

{
  "name": "saas-platform",
  "version": "1.0.0",
  "description": "Multi-tenant SaaS platform",
  
  "llm": {
    "provider": "gemini",
    "model": "gemini-2.5-flash",
    "apiKey": "${GEMINI_API_KEY}",
    "temperature": 0.2,
    "maxTokens": 8192
  },
  
  "targets": {
    "web": {
      "entry": "./src/frontend/app.compose",
      "framework": "nextjs",
      "language": "typescript",
      "output": "./generated/web",
      
      "dependencies": [
        "@tanstack/react-query",
        "zustand",
        "@radix-ui/react-dialog",
        "recharts"
      ],
      
      "assets": [
        ["assets/logo.svg", "public/logo.svg"],
        ["assets/favicon.ico", "public/favicon.ico"],
        ["assets/images", "public/images"]
      ],
      
      "extraRules": [
        "Use React Server Components for data fetching",
        "Implement dark mode with next-themes",
        "All forms use react-hook-form with zod validation"
      ]
    },
    
    "api": {
      "entry": "./src/backend/api.compose",
      "framework": "express",
      "language": "typescript",
      "output": "./generated/api",
      
      "dependencies": [
        "prisma",
        "@prisma/client",
        "zod",
        "bcrypt",
        "jsonwebtoken"
      ],
      
      "extraRules": [
        "Use Prisma for database access",
        "Implement JWT authentication",
        "Add rate limiting to all endpoints"
      ]
    }
  },
  
  "global": {
    "packageManager": "npm",
    "nodeVersion": "20",
    "moduleSystem": "esm"
  }
}

Minimal Example

{
  "llm": {
    "provider": "gemini",
    "model": "gemini-2.5-flash",
    "apiKey": "${GEMINI_API_KEY}"
  },
  
  "targets": {
    "web": {
      "entry": "./app.compose",
      "framework": "nextjs",
      "language": "typescript",
      "output": "./generated/web"
    }
  }
}

Validation Rules

The compiler validates:

  1. llm block exists - Must have LLM configuration
  2. At least one target - Must define at least one target
  3. Required target fields - entry, framework, language, output
  4. Valid provider - Must be gemini, openai, or anthropic
  5. Unique output paths - No two targets can have same output directory
  6. Entry file exists - Entry .compose file must exist
  7. Valid language - Must be a supported language identifier

Error Examples

Missing required field

// ❌ Error: Missing language
{
  "targets": {
    "web": {
      "entry": "./app.compose",
      "framework": "nextjs",
      // Missing: "language": "typescript"
      "output": "./generated/web"
    }
  }
}

No targets defined

// ❌ Error: No targets
{
  "llm": { ... },
  "targets": {}  // Must have at least one target
}

Invalid provider

// ❌ Error: Invalid provider
{
  "llm": {
    "provider": "chatgpt",  // Invalid! Use "openai"
    "model": "gpt-4"
  }
}

Migration from Old Format

Old format:

{
  "targets": {
    "web": {
      "framework": "nextjs",
      "output": "./web"
    }
  },
  "llm": { ... }
}

New format (required fields added):

{
  "llm": { ... },
  "targets": {
    "web": {
      "entry": "./app.compose",     // ← Added
      "framework": "nextjs",
      "language": "typescript",      // ← Added
      "output": "./generated/web"
    }
  }
}

Summary

Required structure:

compose.json
├── llm (required)
│   ├── provider (required)
│   ├── model (required)
│   └── apiKey (required)
└── targets (required, at least one)
    └── [target-name]
        ├── entry (required)
        ├── framework (required)
        ├── language (required)
        └── output (required)

Optional additions:

  • dependencies - npm packages
  • assets - file copying ([from, to] pairs)
  • extraRules - LLM instructions
  • global - global settings