Creating Mendix Domain Model MDL Scripts

SkillCommerce & finance

Lets your agent generate a Mendix domain model, a Claude skill that builds entities, attributes and associations and validates them.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Creating Mendix Domain Model MDL Scripts skill

About this capability

Generate a complete Mendix domain model in MDL, entities, attributes, associations, enumerations, and validate it. Use when asked for a domain model for a business area (e-commerce, HR, CRM, …) rather than a single entity.

What this skill tells your AI

The instructions your AI receives, as published by mendixlabs/mxcli in .claude/skills/mendix/generate-domain-model/SKILL.md and read by ahel’s review.

Use this skill to generate Mendix domain model scripts in MDL (Mendix Definition Language) format and validate them with the linter.

Reference files

SKILL.md covers the process and the decisions — what to model, in what order, and how to check it. The lookup material is next door:

  • reference/syntax.md — the complete syntax for entities, attributes, associations and enumerations, every attribute type, plus reserved keywords and entity positioning. Check a spelling here rather than guessing; a reserved word used as an attribute name fails in Studio Pro, not in the parser.
  • reference/patterns.md — the recurring domain shapes (header/detail, categorisation, audit, soft delete, many-to-many with payload) and a full worked e-commerce model.

When to Use This Skill

  • User asks to create a domain model for a specific use case
  • User wants to generate entities, associations, and enumerations
  • User requests a complete e-commerce, HR, CRM, or other business domain model
  • User needs validation of generated MDL scripts

Modelling for the client: widgets bind members, not expressions

A page widget binds an attribute or association path — never an expression. There is no substring(attr, i, 1) or computed binding in a widget. So a value that must be rendered per-part (each character of a code, each cell of a grid, each of N pencil marks) has to be stored as separate attributes, not packed into one string and indexed client-side. Model the wide form when the UI needs to address the parts individually (e.g. N1…N9 booleans rather than a packed Notes string); reach for a computed/derived value only where a microflow or view-entity OQL produces it into a real attribute. (Same reason the bucket-class idiom exists — see migrate-design-prototype.)

Documentation Best Practices

Entity Documentation

/**
 * Brief one-line summary
 *
 * Detailed multi-line description explaining:
 * - What the entity represents
 * - Key business rules
 * - Relationships to other entities
 *
 * @since 1.0.0
 * @see Module.RelatedEntity
 */

Attribute Documentation

/** Brief description of what this attribute stores */
attributename: type,

Association Documentation

/**
 * Relationship description
 *
 * Explains the business meaning of this association.
 *
 * @since 1.0.0
 */

Step-by-Step Process

1. Analyze Requirements

When user requests a domain model:

  1. Identify core entities (nouns)
  2. Identify enumerations (status, types, categories)
  3. Identify relationships (associations)
  4. Identify attributes for each entity
  5. Check for reserved keyword conflicts

2. Generate MDL Script

Create script with this structure:

-- ============================================================================
-- Domain Model Name
-- ============================================================================
-- Description of the domain
-- ============================================================================

-- MARK: ENUMERATIONS

create enumeration Module.Enum1 (...);
create enumeration Module.Enum2 (...);

-- MARK: CORE ENTITIES

-- MARK: - Entity Group 1

create persistent entity Module.Entity1 (...);
create persistent entity Module.Entity2 (...);

-- MARK: - Entity Group 2

create persistent entity Module.Entity3 (...);

-- MARK: VIEW ENTITIES

create view entity Module.View1 as ...;

-- MARK: ASSOCIATIONS

-- MARK: - Entity Group 1 Associations

create association Module.Assoc1 ...;
create association Module.Assoc2 ...;

3. Validate with Linter

Run the linter to check for issues:

# Standalone test
node dist/test-linter-standalone.js

# or create a custom test file

The linter will detect:

  • ✅ Reserved keywords (CE7247)
  • ✅ Duplicate names (CE0065)
  • ✅ OQL syntax errors (CE0174)

4. Review and Fix Issues

Common Issues:

  1. Reserved Keyword Error:

    error: Reserved keyword 'CreatedDate' used as attribute name
    💡 rename to 'CreationDate'
    

    Fix: Rename to suggested alternative

  2. Duplicate Name Error:

    error: Duplicate name 'Status' in module 'Shop'
    💡 rename one of the enumeration, entity to avoid conflict
    

    Fix: Rename entity to OrderStatus or similar

  3. OQL Syntax Error:

    error: ORDER by requires limit or offset
    💡 add limit clause to query
    

    Fix: Add limit 100 to view entity query

5. Generate Complete Script

Ensure:

  • ✅ All entities have JavaDoc documentation
  • ✅ All attributes have inline comments
  • ✅ All associations have descriptions
  • ✅ Position annotations for all entities
  • ✅ No reserved keywords
  • ✅ No duplicate names
  • ✅ Valid OQL queries

Testing the Script

  1. Save to file: Save as examples/my-domain-model.mdl

  2. Run standalone linter:

    node dist/test-linter-standalone.js
    
  3. Execute in REPL:

    mendix> connect to FILESYSTEM 'path/to/project.mpr';
    mendix> execute script 'examples/my-domain-model.mdl';
    
  4. Check Studio Pro: Open project and verify entities appear correctly

Checklist

Before finalizing an MDL script:

  • All entities have JavaDoc documentation
  • All attributes have inline comments
  • All associations have descriptions
  • Position annotations on all entities
  • MARK comments for files 300+ lines (at least 3 sections)
  • All identifiers quoted with double quotes
  • No duplicate names (run linter)
  • Valid OQL queries in view entities (run linter)
  • Consistent naming conventions (PascalCase)
  • Appropriate data types and lengths
  • Required fields marked with NOT NULL
  • Validation error messages added for NOT NULL and UNIQUE constraints
  • IDs marked with NOT NULL UNIQUE
  • Email/unique fields marked with UNIQUE

References

  • Reserved Keywords: packages/mendix-repl/docs/reference/reserved-keywords.md
  • Linter Proposal: packages/mendix-repl/docs/proposals/mdl-linter-proposal.md
  • Example Scripts:
    • packages/mendix-repl/examples/shop-domain-model.mdl
    • packages/mendix-repl/examples/pet-store-domain-model.mdl
  • Linter Test: packages/mendix-repl/src/test-linter-standalone.ts

Tips for AI Assistants

  1. Always quote all identifiers with double quotes to avoid MDL parser keyword conflicts — but note quoting does not exempt platform-reserved member names (Type, CreatedDate, ChangedDate, Owner, ChangedBy, ID, …); rename those
  2. Use descriptive names (ServiceType, CustomerOrder)
  3. Run linter on generated scripts before presenting to user
  4. Fix all errors reported by linter before finalizing
  5. Follow examples in shop-domain-model.mdl and pet-store-domain-model.mdl
  6. Document thoroughly - Studio Pro users benefit from good documentation
  7. Position thoughtfully - Related entities should be visually grouped
  8. Test incrementally - Generate in sections and validate each part

Signals

GitHub stars
122
Forks
49
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
generate-domain-model
Source
github.com/mendixlabs/mxcli