From content-management-system
Designs page hierarchies, templates with zones and inheritance, page sets, and sitemaps for headless CMS using C# models and page tree APIs.
npx claudepluginhub melodic-software/claude-code-plugins --plugin content-management-systemThis skill is limited to using the following tools:
Guidance for designing page hierarchies, templates, and modular page composition systems for headless CMS.
Designs modular page builders with components, slots, and hybrid patterns for block-based editing. Supports React, Vue, Blazor frameworks via configurable patterns.
Guides design of template aggregation (gallery/hub) and detail pages for programmatic SEO strategies and user-facing template marketplaces in CMS, design tools, website builders, and vibe coding.
Plans or restructures website hierarchy, navigation, URL patterns, breadcrumbs, and internal linking. Use for mapping pages and site sections, excluding XML sitemaps.
Share bugs, ideas, or general feedback.
Guidance for designing page hierarchies, templates, and modular page composition systems for headless CMS.
public class Page
{
public Guid Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Slug { get; set; } = string.Empty;
// Hierarchy
public Guid? ParentId { get; set; }
public Page? Parent { get; set; }
public List<Page> Children { get; set; } = new();
// Computed path
public string Path { get; set; } = string.Empty; // /about/team/leadership
public int Depth { get; set; }
public int Order { get; set; }
// Template and content
public string Template { get; set; } = string.Empty;
public PageContent Content { get; set; } = new();
}
// Page set for grouping related pages
public class PageSet
{
public Guid Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Slug { get; set; } = string.Empty;
public PageSetType Type { get; set; }
// Configuration
public string ItemTemplate { get; set; } = string.Empty;
public string ListTemplate { get; set; } = string.Empty;
public int ItemsPerPage { get; set; } = 10;
// URL pattern
public string UrlPattern { get; set; } = string.Empty; // /blog/{slug}
}
public enum PageSetType
{
Blog, // Chronological posts
Portfolio, // Project showcase
Team, // Team members
Products, // Product catalog
FAQ, // Q&A collection
Custom // User-defined
}
public class PageTemplate
{
public string Name { get; set; } = string.Empty;
public string DisplayName { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
// Template hierarchy
public string? ParentTemplate { get; set; }
// Available zones for content
public List<TemplateZone> Zones { get; set; } = new();
// Required fields
public List<TemplateField> Fields { get; set; } = new();
// Applicable page types
public List<string> ApplicablePageTypes { get; set; } = new();
}
public class TemplateZone
{
public string Name { get; set; } = string.Empty;
public string DisplayName { get; set; } = string.Empty;
public ZoneType Type { get; set; }
public List<string> AllowedWidgets { get; set; } = new();
public int? MaxWidgets { get; set; }
}
public enum ZoneType
{
Single, // One widget only
Multiple, // Multiple widgets stacked
Grid // Grid layout
}
BaseTemplate
├── Zones: Header, Footer, Sidebar
└── Fields: MetaTitle, MetaDescription
├── HomeTemplate (extends Base)
│ └── Zones: Hero, Features, CTA
│
├── ContentTemplate (extends Base)
│ └── Zones: MainContent, RelatedContent
│
└── LandingTemplate (extends Base)
└── Zones: Hero, Sections (multiple)
public abstract class Widget
{
public Guid Id { get; set; }
public string Type { get; set; } = string.Empty;
public int Order { get; set; }
public Dictionary<string, object?> Settings { get; set; } = new();
}
public class TextWidget : Widget
{
public string Content { get; set; } = string.Empty;
}
public class ImageWidget : Widget
{
public Guid MediaItemId { get; set; }
public string? Alt { get; set; }
public string? Caption { get; set; }
}
public class CallToActionWidget : Widget
{
public string Heading { get; set; } = string.Empty;
public string? Subheading { get; set; }
public string ButtonText { get; set; } = string.Empty;
public string ButtonUrl { get; set; } = string.Empty;
public string? BackgroundImageId { get; set; }
}
public class CardGridWidget : Widget
{
public List<Card> Cards { get; set; } = new();
public int Columns { get; set; } = 3;
}
public class PageContent
{
// Zone-based content storage
public Dictionary<string, List<Widget>> Zones { get; set; } = new();
// Page-level fields
public string? HeroTitle { get; set; }
public string? HeroSubtitle { get; set; }
public Guid? HeroImageId { get; set; }
// SEO
public string? MetaTitle { get; set; }
public string? MetaDescription { get; set; }
public bool NoIndex { get; set; }
}
public class SitemapEntry
{
public string Url { get; set; } = string.Empty;
public DateTime LastModified { get; set; }
public ChangeFrequency ChangeFrequency { get; set; }
public decimal Priority { get; set; }
public List<SitemapAlternate>? Alternates { get; set; }
}
public class SitemapAlternate
{
public string Hreflang { get; set; } = string.Empty;
public string Url { get; set; } = string.Empty;
}
public enum ChangeFrequency
{
Always,
Hourly,
Daily,
Weekly,
Monthly,
Yearly,
Never
}
public class SitemapService
{
public async Task<List<SitemapEntry>> GenerateSitemapAsync()
{
var entries = new List<SitemapEntry>();
// Add pages
var pages = await _pageRepository.GetPublishedPagesAsync();
foreach (var page in pages)
{
entries.Add(new SitemapEntry
{
Url = $"{_baseUrl}{page.Path}",
LastModified = page.ModifiedUtc,
ChangeFrequency = GetChangeFrequency(page),
Priority = CalculatePriority(page)
});
}
// Add page set items (blog posts, products, etc.)
var pageSets = await _pageSetRepository.GetAllAsync();
foreach (var pageSet in pageSets)
{
var items = await _pageSetRepository.GetItemsAsync(pageSet.Id);
foreach (var item in items)
{
var url = GenerateUrl(pageSet.UrlPattern, item);
entries.Add(new SitemapEntry
{
Url = url,
LastModified = item.ModifiedUtc,
ChangeFrequency = ChangeFrequency.Weekly,
Priority = 0.6m
});
}
}
return entries;
}
private decimal CalculatePriority(Page page)
{
// Home page highest priority
if (page.Depth == 0) return 1.0m;
// Decrease by depth
return Math.Max(0.5m, 1.0m - (page.Depth * 0.1m));
}
}
GET /api/pages # Root pages
GET /api/pages/{id} # Single page
GET /api/pages/{id}/children # Child pages
GET /api/pages/path/{*path} # Page by URL path
GET /api/pages/tree # Full page tree
GET /api/sitemap.xml # XML sitemap
GET /api/sitemap.json # JSON sitemap
{
"data": {
"id": "page-123",
"title": "About Us",
"slug": "about",
"path": "/about",
"template": "ContentTemplate",
"depth": 1,
"order": 2,
"children": [
{
"id": "page-456",
"title": "Our Team",
"slug": "team",
"path": "/about/team",
"template": "TeamTemplate",
"children": []
},
{
"id": "page-789",
"title": "Careers",
"slug": "careers",
"path": "/about/careers",
"template": "ContentTemplate",
"children": []
}
]
},
"breadcrumbs": [
{ "title": "Home", "path": "/" },
{ "title": "About Us", "path": "/about" }
]
}
| Pattern | When to Use |
|---|---|
| Flat structure | Simple sites, few pages |
| 2-level hierarchy | Most corporate sites |
| Deep hierarchy | Documentation, large catalogs |
| Page sets | Blog, portfolio, team pages |
DO:
- Keep zones semantic (Header, MainContent, Sidebar)
- Allow flexible widget placement
- Inherit common zones from base template
- Provide sensible defaults
DON'T:
- Create overly specific templates
- Hard-code layout in templates
- Mix content and presentation concerns
- Create deep template inheritance chains
navigation-architecture - Menu and breadcrumb designurl-routing-patterns - URL structure and routingcontent-type-modeling - Page as content type