admin-customize
Customize the admin UI with swappable pages and layout slots. Use when replacing built-in pages (dashboard, list, edit, view), injecting content into layout slots (header, footer, sidebar, before/after), or registering per-collection overrides.
Best use case
admin-customize is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Customize the admin UI with swappable pages and layout slots. Use when replacing built-in pages (dashboard, list, edit, view), injecting content into layout slots (header, footer, sidebar, before/after), or registering per-collection overrides.
Teams using admin-customize should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/admin-customize/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How admin-customize Compares
| Feature / Agent | admin-customize | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Customize the admin UI with swappable pages and layout slots. Use when replacing built-in pages (dashboard, list, edit, view), injecting content into layout slots (header, footer, sidebar, before/after), or registering per-collection overrides.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Admin Customization — Swappable Pages & Layout Slots
Guide for customizing the Momentum CMS admin UI via page replacements and layout slot injection.
## Arguments
- `$ARGUMENTS` - What to customize: `page-override`, `slot`, or `per-collection`
## Two Registration Methods
### 1. Config-level (momentum.config.ts)
Registered in the server config. The code generator emits these as loader functions in the browser-safe generated config. This is the recommended approach — single source of truth.
### 2. Provider-level (app.config.ts)
Registered via Angular DI providers. Useful for app-specific customizations that don't belong in the server config, or for login page slots (which render outside the admin shell).
## Swappable Pages (Full Replacement)
### Available Page Keys
| Key | Built-in Page |
| ----------------- | --------------- |
| `dashboard` | Dashboard |
| `login` | Login |
| `media` | Media Library |
| `collection-list` | Collection List |
| `collection-edit` | Collection Edit |
| `collection-view` | Collection View |
| `global-edit` | Global Edit |
### Config-level (momentum.config.ts)
```typescript
import { defineMomentumConfig } from '@momentumcms/core';
export default defineMomentumConfig({
// ...
admin: {
basePath: '/admin',
components: {
dashboard: () => import('./app/custom-dashboard.component').then((m) => m.CustomDashboard),
},
},
});
```
### Provider-level (app.config.ts)
```typescript
import { provideAdminComponent } from '@momentumcms/admin';
export const appConfig: ApplicationConfig = {
providers: [
provideAdminComponent('dashboard', () =>
import('./custom-dashboard.component').then((m) => m.CustomDashboard),
),
],
};
```
### Per-Collection Page Overrides
Override pages for a specific collection only. Other collections keep the default.
#### Config-level (on the collection definition)
```typescript
const collections = baseCollections.map((c) => {
if (c.slug === 'articles') {
return {
...c,
admin: {
...c.admin,
components: {
list: () =>
import('./app/custom-articles-list.component').then(
(m) => m.CustomArticlesListComponent,
),
},
},
};
}
return c;
});
```
#### Provider-level
```typescript
provideAdminComponent('collections/articles/list', () =>
import('./custom-articles-list.component').then((m) => m.CustomArticlesList),
);
```
### Resolution Chain
For collection pages, the resolver checks in order:
1. Per-collection override (`collections/{slug}/{type}`)
2. Global override (`collection-list`)
3. Built-in default
## Layout Slots (Additive Injection)
Slots inject content around existing pages without replacing them. Multiple components can be registered for the same slot.
### Available Slots
#### Shell Slots (visible on all authenticated pages)
| Slot Key | Position |
| ----------------- | ------------------------------- |
| `shell:header` | Top of main content area |
| `shell:footer` | Bottom of main content area |
| `shell:nav-start` | After Dashboard link in sidebar |
| `shell:nav-end` | After plugin routes in sidebar |
#### Page Slots
| Slot Key | Position |
| -------------------------------------- | ------------------------ |
| `dashboard:before/after` | Around dashboard content |
| `collection-list:before/after` | Around list tables |
| `collection-edit:before/after/sidebar` | Around edit forms |
| `collection-view:before/after` | Around view pages |
| `login:before/after` | Around login form |
### Config-level (momentum.config.ts — admin.components)
Config-level slots use camelCase keys that map to slot positions:
| Config Key | Slot Position |
| ------------------ | ------------------ |
| `beforeNavigation` | `shell:nav-start` |
| `afterNavigation` | `shell:nav-end` |
| `header` | `shell:header` |
| `footer` | `shell:footer` |
| `beforeDashboard` | `dashboard:before` |
| `afterDashboard` | `dashboard:after` |
| `beforeLogin` | `login:before` |
| `afterLogin` | `login:after` |
```typescript
admin: {
components: {
beforeDashboard: () =>
import('./app/announcement-banner.component').then((m) => m.AnnouncementBanner),
footer: () =>
import('./app/custom-footer.component').then((m) => m.CustomFooter),
},
},
```
### Config-level (per-collection slots)
```typescript
// In the collection definition:
admin: {
components: {
beforeList: () => import('./articles-filter.component').then((m) => m.ArticlesFilter),
editSidebar: () => import('./meta-panel.component').then((m) => m.MetaPanel),
beforeView: () => import('./status-badge.component').then((m) => m.StatusBadge),
},
},
```
Per-collection config keys: `beforeList`, `afterList`, `beforeEdit`, `afterEdit`, `editSidebar`, `beforeView`, `afterView`.
### Provider-level (app.config.ts)
```typescript
import { provideAdminSlot } from '@momentumcms/admin';
providers: [
// Global slot (all pages)
provideAdminSlot('shell:header', () =>
import('./env-banner.component').then((m) => m.EnvBanner),
),
// Per-collection slot
provideAdminSlot('collection-list:before:articles', () =>
import('./articles-filter.component').then((m) => m.ArticlesFilter),
),
],
```
### Per-Collection Slot Merging
When viewing a collection page, both global and per-collection slot components render (global first, then per-collection).
## Component Conventions
Custom components receive context via Angular inputs:
```typescript
import { ChangeDetectionStrategy, Component, input } from '@angular/core';
import type { CollectionConfig } from '@momentumcms/core';
@Component({
selector: 'app-custom-slot',
host: { class: 'block' },
template: `
<div class="p-4 bg-mcms-muted rounded-lg">
@if (collection(); as col) {
<p>Collection: {{ col.slug }}</p>
}
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class CustomSlotComponent {
readonly collection = input<CollectionConfig>();
readonly entityId = input<string>();
}
```
## After Making Changes
1. If you modified `momentum.config.ts`, regenerate the browser-safe config:
```bash
nx run <app>:generate # or npm run generate in generated apps
```
2. The generated config at `src/generated/momentum.config.ts` will include the component loaders with correct import paths.
3. Provider-level changes in `app.config.ts` take effect immediately (no generation needed).
## Plugin Registration
Plugins can declare admin component overrides:
```typescript
const myPlugin: MomentumPlugin = {
name: 'my-plugin',
adminComponents: {
beforeDashboard: () => import('./plugin-banner').then((m) => m.PluginBanner),
header: () => import('./custom-header').then((m) => m.CustomHeader),
},
};
```
## Exports from @momentumcms/admin
```typescript
import {
provideAdminComponent, // Register page override via DI
provideAdminSlot, // Register slot component via DI
} from '@momentumcms/admin';
```
## Related Files
- `libs/core/src/lib/config.ts` — `AdminComponentsConfig` (global slots/pages)
- `libs/core/src/lib/collections/collection.types.ts` — `CollectionAdminComponentsConfig` (per-collection)
- `libs/admin/src/lib/services/admin-component-registry.service.ts` — Page resolver registry
- `libs/admin/src/lib/services/admin-slot-registry.service.ts` — Slot registry
- `libs/admin/src/lib/services/provide-admin-components.ts` — Provider functions
- `libs/admin/src/lib/components/admin-page-resolver/` — Route-level page resolver
- `libs/admin/src/lib/components/admin-slot-outlet/` — Slot rendering component
- `docs/admin/customization.md` — User-facing documentationRelated Skills
admin-config
Wire admin routes, configure browser-safe plugin imports, and create custom field renderers. Use when setting up momentumAdminRoutes, browserImports, or FieldRendererRegistry.
headless-ui
Use @momentumcms/headless inside generated Momentum apps. Use when building custom public UI, composing accessible primitives, configuring global styles for hdl-* elements, or adding app-level tests around headless interactions.
ui-audit
Comprehensive UI component audit for Momentum CMS. Use when asked to audit, review, check, or validate a UI component. Checks Storybook stories, interaction tests, variants, kitchen sink integration, admin dashboard usage, accessibility, and responsive design (mobile-first). AUTOMATICALLY FIXES issues found and verifies with visual inspection. Triggers include "audit button", "review the card component", "check accessibility of tabs", or "/ui-audit <component-name>".
test-all
Run the FULL Momentum CMS test suite — every single suite, no skips. Triggers on "test all", "test everything", "run all tests", "run the test all script", "test-all script", "run the full suite", "run every test", "test the whole thing", "make sure everything passes", "run test:all", or ANY variation asking to run all/every/full tests. Also triggers on typos like "test al", "tets all", "tes all". NEVER skip suites unless the user EXPLICITLY names suites to skip.
stroll-test
End-to-end CLI stroll test of npm-published Momentum CMS packages. Scaffolds a fresh project with create-momentum-app, adds all plugins, runs migrations, starts server, and verifies everything works. Triggers include "stroll test", "cli stroll", "test published packages", or "/stroll-test".
skill-improve
Self-improving skill loop. Analyzes eval failures, rewrites the skill, re-evaluates, and repeats until convergence. Run after /skill-eval produces baseline results.
skill-eval
Run structured evaluations comparing skill vs no-skill performance. Measures assertion pass rates, timing, and output quality to systematically improve skills.
prepare-release
Prepare a patch/minor/major version release for all Momentum CMS packages. Bumps versions, generates changelogs, verifies builds/tests, adds new packages to Nx release config, and commits. Triggers include "prepare release", "bump version", "release patch", or "/prepare-release".
momentum-api
Work with Momentum API for data operations in Angular components
migrations
Run migrations, generate schemas, and manage code generation for Momentum CMS. Use when working with database migrations, Drizzle schema generation, type generation, or Angular schematics.
mcp-setup
Set up the Momentum CMS MCP server plugin and generate Claude Code MCP config for AI tool integration. Use when connecting Claude Code (or any MCP client) to a Momentum CMS instance.
SYSTEM ROLE & BEHAVIORAL PROTOCOLS
**ROLE:** Senior Frontend Architect & Avant-Garde UI Designer.