page-structure-design
Use when designing page hierarchies, page templates, layout zones, or sitemap structures. Covers page sets, template inheritance, component zones, and page tree APIs for headless CMS architectures.
安装与使用
请根据来源仓库和你的 AI 工具说明安装此技能。先阅读技能文件和依赖要求,再添加到工作流。
查看来源 ↗使用指南技能说明
Page Structure Design
Guidance for designing page hierarchies, templates, and modular page composition systems for headless CMS.
When to Use This Skill
- Designing page tree structures
- Creating page templates with zones
- Implementing page builder functionality
- Planning sitemap generation
- Building modular page composition
Page Hierarchy Patterns
Basic Page Tree
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 Sets (Collections)
// 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
}
Template System
Template Definition
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
}
Template Inheritance
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)
Page Builder Components
Widget System
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;
}
Page Content Structure
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; }
}
Sitemap Generation
Sitemap Data Model
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
}
Sitemap Generation Service
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));
}
}
Page Tree API
REST Endpoints
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
Page Tree Response
{
"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" }
]
}
Best Practices
Page Structure
| 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 |
Template Design
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
Related Skills
-
navigation-architecture- Menu and breadcrumb design -
url-routing-patterns- URL structure and routing -
content-type-modeling- Page as content type
使用示例
查看来源仓库中的使用示例与配置说明。
查看来源 ↗来源历史
- 收录时间
- 2026-01-20
- 索引更新时间
- 2026-02-04
- Branch
- main
收录与同步日期属于本站记录。源码修改历史请查看来源仓库。
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!