Generation

Multi-Collection Configuration

Manage multiple collections with a configuration file

For larger projects with multiple collections, use a configuration file to generate and manage them all at once.

Choosing a Config Format

There are two configuration formats available. Choose based on your needs:

Use CaseFormatKey
All collections share the same schemaSimple formatschemaPath
Each collection has its own schemaEnhanced formatcollections[]
Multiple layers with targetsEnhanced formatcollections[] + targets[]
Important: When using schemaPath, it must point to a file, not a directory. If you have multiple schema files in a directory, use the enhanced format with collections[] instead.

Simple Format (Single Schema)

For quick prototyping when all collections use the same field structure:

// crouton.config.js
export default {
  schemaPath: './my-schema.json',  // Must be a FILE path
  dialect: 'sqlite',
  targets: [
    { layer: 'shop', collections: ['products'] }
  ]
}

Enhanced Format (Multiple Schemas)

For production projects where each collection has its own schema:

// crouton.config.js
export default {
  collections: [
    { name: 'products', fieldsFile: './schemas/products.json' },
    { name: 'categories', fieldsFile: './schemas/categories.json' },
  ],
  dialect: 'sqlite',
  targets: [
    { layer: 'shop', collections: ['products', 'categories'] }
  ]
}
Recommended: Use the enhanced format for most projects. It's more flexible and makes it clear which schema belongs to which collection.

Config File Structure

// crouton.config.js
export default {
  // Define all collections
  collections: [
    { name: 'products', fieldsFile: './schemas/product.json' },
    { name: 'categories', fieldsFile: './schemas/category.json', hierarchy: true },
    { name: 'orders', fieldsFile: './schemas/order.json' },
    { name: 'posts', fieldsFile: './schemas/post.json' },
    { name: 'slides', fieldsFile: './schemas/slide.json', sortable: true },
    { name: 'bookings', fieldsFile: './schemas/booking.json', collab: true },
    { name: 'users', fieldsFile: './schemas/user.json' },
    { name: 'roles', fieldsFile: './schemas/role.json' },
  ],

  // Organize into layers
  targets: [
    {
      layer: 'shop',
      collections: ['products', 'categories', 'orders']
    },
    {
      layer: 'blog',
      collections: ['posts', 'slides']
    },
    {
      layer: 'admin',
      collections: ['users', 'roles']
    }
  ],

  // Database
  dialect: 'sqlite',  // or 'pg'

  // Translations (i18n) - define translatable fields per collection
  translations: {
    collections: {
      products: ['name', 'description'],
      posts: ['title', 'content']
    }
  },

  // Flags
  flags: {
    force: false,           // Overwrite existing files?
    noTranslations: false,  // Skip translations?
    noDb: false,           // Skip database generation?
    dryRun: false,         // Preview only?
    autoRelations: true,   // Generate relation stubs?
    useMetadata: true      // Add createdAt/updatedAt?
  }
}

Generate from Config

# Generate all collections
npx crouton-generate config ./crouton.config.js

# With flags
npx crouton-generate config ./crouton.config.js --force --dry-run

Configuration Options

Collections Array

Define all your collections in one place:

collections: [
  { name: 'products', fieldsFile: './schemas/product.json' },
  { name: 'categories', fieldsFile: './schemas/category.json' },
]

Each collection object requires:

  • name - Collection name (plural)
  • fieldsFile - Path to schema JSON file

Optional collection properties:

  • hierarchy - Enable tree structure (adds parentId, path, depth, order fields)
  • sortable - Enable drag-to-reorder (adds order field and reorder endpoint)
  • collab - Enable presence indicators (shows who's editing items in realtime)

Targets Array

Organize collections into layers:

targets: [
  {
    layer: 'shop',
    collections: ['products', 'categories', 'orders']
  },
  {
    layer: 'blog',
    collections: ['posts', 'authors', 'comments']
  }
]

This creates a clean domain-driven structure:

layers/
  ├── shop/
  │   └── collections/
  │       ├── products/
  │       │   └── app/
  │       │       ├── components/
  │       │       └── composables/
  │       ├── categories/
  │       │   └── app/
  │       │       ├── components/
  │       │       └── composables/
  │       └── orders/
  │           └── app/
  │               ├── components/
  │               └── composables/
  └── blog/
      └── collections/
          ├── posts/
          │   └── app/
          │       ├── components/
          │       └── composables/
          ├── authors/
          │   └── app/
          │       ├── components/
          │       └── composables/
          └── comments/
              └── app/
                  ├── components/
                  └── composables/

Database Dialect

Specify your database type:

dialect: 'sqlite'  // or 'pg'

This affects the generated migrations and database schema.

Translations Configuration

Define which fields should be translatable per collection:

translations: {
  collections: {
    // Products: translate name and description
    products: ['name', 'description'],

    // Posts: translate title and content
    posts: ['title', 'content', 'excerpt'],

    // Pages: full content translation
    pages: ['title', 'content', 'metaTitle', 'metaDescription']
  }
}

When translations are configured:

  1. Listed fields get CroutonI18nInput in forms for per-language editing
  2. Data is stored as: { translations: { en: {...}, nl: {...} } }
  3. The i18n layer is automatically added to nuxt.config.ts
  4. Locale files are created in layers/[layer]/i18n/locales/
Note: If you don't need translations, set flags.noTranslations: true to skip all i18n code generation.

Flags

Control the generation behavior:

flags: {
  force: false,           // Overwrite existing files?
  noTranslations: false,  // Skip translations?
  noDb: false,           // Skip database generation?
  dryRun: false,         // Preview only?
  autoRelations: true,   // Generate relation stubs?
  useMetadata: true      // Add createdAt/updatedAt?
}

Project Templates

Create reusable templates for common project types:

SaaS Starter Template

// templates/saas-starter.config.js
export default {
  collections: [
    { name: 'users', fieldsFile: './schemas/user.json' },
    { name: 'teams', fieldsFile: './schemas/team.json' },
    { name: 'subscriptions', fieldsFile: './schemas/subscription.json' },
    { name: 'billing', fieldsFile: './schemas/billing.json' },
  ],
  targets: [
    {
      layer: 'admin',
      collections: ['users', 'teams', 'subscriptions', 'billing']
    }
  ],
  flags: {
    useMetadata: true
  }
}

E-commerce Template

// templates/ecommerce.config.js
export default {
  collections: [
    { name: 'products', fieldsFile: './schemas/product.json' },
    { name: 'categories', fieldsFile: './schemas/category.json' },
    { name: 'orders', fieldsFile: './schemas/order.json' },
    { name: 'customers', fieldsFile: './schemas/customer.json' },
    { name: 'inventory', fieldsFile: './schemas/inventory.json' },
  ],
  targets: [
    {
      layer: 'shop',
      collections: ['products', 'categories', 'inventory']
    },
    {
      layer: 'orders',
      collections: ['orders', 'customers']
    }
  ],
  dialect: 'pg',
  flags: {
    useMetadata: true,
    autoRelations: true
  }
}

Blog Platform Template

// templates/blog.config.js
export default {
  collections: [
    { name: 'posts', fieldsFile: './schemas/post.json' },
    { name: 'authors', fieldsFile: './schemas/author.json' },
    { name: 'categories', fieldsFile: './schemas/category.json' },
    { name: 'tags', fieldsFile: './schemas/tag.json' },
    { name: 'comments', fieldsFile: './schemas/comment.json' },
  ],
  targets: [
    {
      layer: 'blog',
      collections: ['posts', 'authors', 'categories', 'tags', 'comments']
    }
  ],
  dialect: 'sqlite',
  flags: {
    noTranslations: false,  // Enable translations for content
    useMetadata: true
  }
}

Using Templates

Copy a template to your project and generate:

# Copy template
cp templates/saas-starter.config.js ./crouton.config.js

# Customize as needed
nano crouton.config.js

# Generate collections
npx crouton-generate config ./crouton.config.js

Best Practices

Organize by Domain

Group related collections into layers:

targets: [
  { layer: 'shop', collections: ['products', 'categories'] },
  { layer: 'blog', collections: ['posts', 'authors'] },
  { layer: 'admin', collections: ['users', 'roles'] }
]

Use Dry Run First

Preview changes before generating:

npx crouton-generate config ./crouton.config.js --dry-run

Version Control Your Config

Commit your config file and schemas:

git add crouton.config.js schemas/
git commit -m "Add collection configuration"

Keep Schemas Separate

Store schemas in a dedicated directory:

project/
  ├── crouton.config.js
  └── schemas/
      ├── product.json
      ├── category.json
      └── order.json

Regenerating Collections

When you need to update generated code:

# Regenerate with force flag
npx crouton-generate config ./crouton.config.js --force

Using --force will overwrite existing files. Make sure to commit your changes first or back up any customizations.

Next Steps