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: '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 'postgres', 'mysql'

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

  // External connectors (for :referenced collections)
  connectors: {
    users: {
      type: 'supersaas',      // Connector type
      autoInstall: true,       // Install package automatically
      updateAppConfig: true    // Register in app.config.ts automatically
    }
  },

  // 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?
    useTeamUtility: true,  // Enable team-based auth?
    useMetadata: true,     // Add createdAt/updatedAt?
    autoConnectors: true   // Auto-setup connectors without prompts
  }
}

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)

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/
  │   ├── components/
  │   │   ├── products/
  │   │   ├── categories/
  │   │   └── orders/
  │   └── composables/
  └── blog/
      ├── components/
      │   ├── posts/
      │   ├── authors/
      │   └── comments/
      └── composables/

Database Dialect

Specify your database type:

dialect: 'sqlite'  // or 'postgres', 'mysql'

This affects the generated migrations and database schema.

External Connectors

Configure automatic setup for external collections (like users from your auth system):

connectors: {
  users: {
    type: 'supersaas',      // Connector type: 'supersaas'
    autoInstall: true,       // Install @friendlyinternet/nuxt-crouton-supersaas
    updateAppConfig: true    // Auto-register in app.config.ts
  }
}

When you reference external collections in your schemas using :users prefix, the generator will:

  1. Install the SuperSaaS package automatically
  2. Add the SuperSaaS layer to nuxt.config.ts
  3. Import and register the collection in app.config.ts

Learn more about SuperSaaS integration in the SuperSaaS Integration Guide

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?
  useTeamUtility: true,  // Enable team-based auth?
  useMetadata: true,     // Add createdAt/updatedAt?
  autoConnectors: true   // Auto-setup connectors (use connectors config above)
}

Key flags:

  • autoConnectors: true - Uses the connectors configuration above without prompting
  • autoConnectors: false - Prompts interactively when external references are detected

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: {
    useTeamUtility: true,
    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: 'postgres',
  flags: {
    useTeamUtility: true,
    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