What is Concerto?
Concerto provides a type-safe way to model business data. It’s similar to TypeScript interfaces or JSON Schema, but designed specifically for business and legal use cases. Every template in the playground must have a corresponding Concerto model.Concerto models are defined in
.cto files and use a syntax that’s easy to read and write, even if you’re not a developer.Basic model structure
Every Concerto model starts with a namespace declaration:namespace [email protected]- Defines a unique identifier and version for your model@template- Annotation marking this as the root template conceptconcept HelloWorld- Defines a data structure named HelloWorldo String name- Declares a required string property called “name”
The
@template annotation is required on the root concept that your template will use.Property types
Concerto supports various property types:Primitive types
Arrays
Use[] to denote array types:
Optional properties
Add theoptional keyword:
Nested concepts
You can compose complex models by nesting concepts:Customer contains an Address object.
Real-world example: Employment offer
Here’s a complete model for an employment offer letter:- A
MonetaryAmountconcept for representing salary - A
Probationconcept for probation period details - The main
EmploymentOffertemplate with required and optional fields
Enumerations
Define a fixed set of values using enums:Importing external models
You can import concepts from other namespaces:MonetaryAmount concept from the Accord Project’s model repository.
Complex example: Order system
Here’s a sophisticated model with multiple nested concepts and arrays:- Multiple nested concepts (Address, Order, OrderLine)
- Arrays of primitives (
String[]) and concepts (OrderLine[]) - Optional fields
- External imports
How models are used
The ModelManager in the playground loads and validates your Concerto model:store.ts:80-82, you can see the model is:
- Added to the ModelManager in strict mode
- Validated for syntax and semantic correctness
- External models are fetched and loaded
Validation
When you provide data to a template, it must match the model structure:$class property is required and must reference the fully qualified name of a concept in your model.
Every JSON object must have a
$class property that identifies its type. This enables runtime type checking and validation.Common patterns
Reusable concepts
Define common concepts that can be reused across multiple templates:Optional nested objects
Combine optional with nested concepts:Arrays of nested objects
NDA example
A simple but complete Non-Disclosure Agreement model:Best practices
Use semantic naming
Use semantic naming
Name your concepts and properties to reflect their business meaning, not technical implementation. Use
candidateName instead of name1, annualSalary instead of amount.Add documentation
Add documentation
Use comments to explain the purpose of concepts and properties, especially for complex business logic.
Version your namespaces
Version your namespaces
Always include a version number in your namespace (e.g.,
@1.0.0). This allows for model evolution over time.Make fields optional thoughtfully
Make fields optional thoughtfully
Only mark fields as optional if they truly are optional in the business context. Required fields enforce data completeness.
Next steps
Data binding
Learn how your models bind to template variables
Template engine
Understand how the engine processes templates and models