| name | collection |
| description | Generate a new Momentum CMS collection with fields, access control, and hooks |
| argument-hint | <collection-name> |
Generate Momentum CMS Collection
Create a new collection file following project conventions.
Arguments
$ARGUMENTS - Collection name (e.g., "posts", "products", "users")
Important: Collection Location
All collections are defined in libs/example-config/src/collections/. Both example apps (example-angular, example-analog) import from @momentumcms/example-config/collections. Never define collections in individual apps.
Steps
-
Create the collection file at libs/example-config/src/collections/<name>.collection.ts
-
Use this template:
import {
defineCollection,
text,
richText,
number,
date,
checkbox,
select,
relationship,
} from '@momentumcms/core';
export const <PascalName> = defineCollection({
slug: '<kebab-name>',
admin: {
useAsTitle: 'title',
defaultColumns: ['title', 'createdAt'],
group: 'Content',
icon: 'heroNewspaper',
},
access: {
read: () => true,
create: ({ req }) => !!req.user,
update: ({ req }) => req.user?.role === 'admin',
delete: ({ req }) => req.user?.role === 'admin',
},
hooks: {
beforeChange: [],
afterChange: [],
},
fields: [
text('title', { required: true }),
],
});
- Export from
libs/example-config/src/collections/index.ts:
import { <PascalName> } from './<name>.collection';
export const collections: CollectionConfig[] = [
<PascalName>,
];
export {
<PascalName>,
};
Both example apps automatically pick up changes since they import from @momentumcms/example-config/collections.
- Remind user: if migration mode is enabled, run
nx run <app>:migrate:generate after collection changes to create a migration file.
Field Types Available
Text Input Fields
text(name, options) - Short text with optional min/max length
textarea(name, options) - Multi-line text with optional rows
richText(name, options) - Rich text editor
email(name, options) - Email input
password(name, options) - Password input with optional min length
Numeric & Date Fields
number(name, options) - Numeric value with optional min/max/step
date(name, options) - Date/datetime picker
Boolean & Selection Fields
checkbox(name, options) - Boolean checkbox
select(name, { options: [...] }) - Dropdown select (supports hasMany)
radio(name, { options: [...] }) - Radio button group
Media & Files
upload(name, options) - File upload with MIME type filtering
Relationship & Data Fields
relationship(name, { collection: () => Ref }) - Reference to another collection (supports hasMany, polymorphic)
array(name, { fields: [...] }) - Array of nested fields
group(name, { fields: [...] }) - Nested object grouping
blocks(name, { blocks: [...] }) - Block-based content
json(name, options) - Raw JSON field
point(name, options) - Geolocation point
slug(name, { from: 'fieldName' }) - Auto-generated slug from another field
Layout Fields (non-data storing)
tabs(tabs: [...]) - Tabbed sections for organization
collapsible(label, { fields: [...] }) - Collapsible section
row(fields: [...]) - Horizontal row layout
Sidebar Icons
All heroicons/outline (324 icons) are provided globally at the admin route level. Just set admin.icon to any hero* name — no manual registration needed.
The sidebar resolves icons via: collection.admin.icon → collectionIcons[slug] fallback map → 'heroFolder' default. To add a slug-based fallback, update collectionIcons in libs/admin/src/lib/widgets/admin-sidebar/admin-sidebar.component.ts.
Browse available icons at Heroicons. Naming: hero + PascalCase (e.g., heroEnvelopeOpen for envelope-open).