Page Templates¶
Page templates are full-slide layout primitives. Use them to decide the structure of a page before filling in block content.
AI Agent Guidance¶
When building a deck, follow this decision order:
- Choose a page template - determines the layout structure
- Choose block styles - fill the content areas with reusable blocks
- Configure props - customize title, variant, content
Rules for AI agents:
- Use the simplest page template that faithfully represents the intent
- Check src/page-templates/registry.ts for the canonical list
- Only add a new page template when existing ones cannot express the page cleanly
- Page templates accept React.ReactNode children - you can nest blocks inside them
Current Page Templates¶
1. hero - Hero Slide¶
Purpose: Title-first cover slide for deck opening and section transitions.
Source: src/shared/design-system/slide-templates/HeroSlideTemplate.tsx
Interface:
interface HeroSlideConfig {
title: string;
subtitle: string;
metadata?: Array<{ label: string; value: string }>;
variant?: 'default' | 'gradient' | 'dark';
titleColor?: string;
}
Props:
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
title |
string |
✅ | - | Main heading text |
subtitle |
string |
✅ | - | Secondary text below title |
metadata |
Array<{label, value}> |
❌ | [] |
Key-value pairs displayed below subtitle |
variant |
'default' \| 'gradient' \| 'dark' |
❌ | 'default' |
Visual style variant |
titleColor |
string |
❌ | theme default | Custom title color (CSS color value) |
Variants:
- default - Standard dark text on light background
- gradient - Gradient text effect using theme gradient
- dark - Light text on dark background
Example:
import { HeroSlideTemplate } from '../shared/design-system/slide-templates';
<HeroSlideTemplate
title="E3Pro Training"
subtitle="Product overview and technical specifications"
metadata={[
{ label: 'Version', value: 'v2.1' },
{ label: 'Duration', value: '45 min' }
]}
variant="gradient"
/>
When to use: - Deck opening slide - Section divider/transition slides - Title-first communication
2. bullet-list - Bullet List Slide¶
Purpose: Single-column list slide for concise points.
Source: src/shared/design-system/slide-templates/BulletListSlideTemplate.tsx
Interface:
interface BulletListConfig {
title: string;
description?: string;
items: Array<string | { text: string; highlight?: boolean }>;
variant?: 'default' | 'dark';
}
Props:
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
title |
string |
✅ | - | Slide title |
description |
string |
❌ | undefined |
Optional description below title |
items |
Array<string \| {text, highlight}> |
✅ | - | List items (string or object with optional highlight) |
variant |
'default' \| 'dark' |
❌ | 'default' |
Visual style variant |
Item format:
- Simple string: "Point text" → rendered as bullet point
- Object: { text: "Point text", highlight: true } → bold bullet point
Example:
import { BulletListSlideTemplate } from '../shared/design-system/slide-templates';
<BulletListSlideTemplate
title="Key Features"
description="What makes E3Pro competitive"
items={[
'IP67 waterproof rating',
'Integrated GPS + GLONASS',
{ text: '2-year warranty included', highlight: true },
'Compatible with all OVES chargers'
]}
variant="default"
/>
When to use: - Feature lists - Benefits enumeration - Key takeaways - Any sequential or unordered points
3. two-column - Two Column Slide¶
Purpose: Balanced comparison layout with left and right content areas.
Source: src/shared/design-system/slide-templates/TwoColumnSlideTemplate.tsx
Interface:
interface TwoColumnConfig {
title: string;
leftContent: React.ReactNode;
rightContent: React.ReactNode;
variant?: 'default' | 'dark';
}
Props:
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
title |
string |
✅ | - | Slide title |
leftContent |
React.ReactNode |
✅ | - | Left column content (can be block component) |
rightContent |
React.ReactNode |
✅ | - | Right column content (can be block component) |
variant |
'default' \| 'dark' |
❌ | 'default' |
Visual style variant |
Layout: CSS Grid, 2 equal columns (1fr 1fr), gap from theme spacing.
Example:
import { TwoColumnSlideTemplate } from '../shared/design-system/slide-templates';
import { StatCardsBlock } from '../blocks/StatCardsBlock';
<TwoColumnSlideTemplate
title="Before vs After"
leftContent={
<StatCardsBlock
cards={[
{ label: 'Range', value: '45km' },
{ label: 'Charge Time', value: '6h' }
]}
/>
}
rightContent={
<StatCardsBlock
cards={[
{ label: 'Range', value: '70km' },
{ label: 'Charge Time', value: '3.5h' }
]}
/>
}
variant="default"
/>
When to use: - Comparisons (before/after, old/new, competitor analysis) - Side-by-side feature breakdowns - Pros/cons layouts - Any content needing parallel structure
4. timeline - Timeline Slide¶
Purpose: Sequential roadmap layout for milestones and phases.
Source: src/shared/design-system/slide-templates/TimelineSlideTemplate.tsx
Interface:
interface TimelinePhase {
title: string;
description: string;
}
interface TimelineConfig {
title: string;
phases: TimelinePhase[];
variant?: 'default' | 'dark';
}
Props:
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
title |
string |
✅ | - | Slide title |
phases |
Array<{title, description}> |
✅ | - | Sequential phases/milestones |
variant |
'default' \| 'dark' |
❌ | 'default' |
Visual style variant |
Phase object:
- title (string, required) - Phase name (e.g., "Phase 1: Planning")
- description (string, required) - Phase details
Example:
import { TimelineSlideTemplate } from '../shared/design-system/slide-templates';
<TimelineSlideTemplate
title="Implementation Roadmap"
phases={[
{
title: 'Phase 1: Setup',
description: 'Install hardware and configure network'
},
{
title: 'Phase 2: Pilot',
description: 'Deploy to 5 locations, collect feedback'
},
{
title: 'Phase 3: Rollout',
description: 'Full deployment across all 50 locations'
}
]}
variant="default"
/>
When to use: - Project roadmaps - Implementation plans - Historical timelines - Process flows (sequential phases) - Milestone tracking
Page Template Selection Decision Tree¶
Start: What is the primary communication goal?
├─ Title/section opener?
│ └─ Use: hero
│
├─ List of points?
│ ├─ Sequential steps? → Use: bullet-list (consider numbered-list block)
│ └─ Unordered points? → Use: bullet-list
│
├─ Comparison?
│ ├─ Two sides? → Use: two-column
│ └─ Multi-item comparison? → Use: bullet-list + comparison-table block
│
├─ Timeline/roadmap?
│ └─ Use: timeline
│
└─ None of above?
└─ Consider: two-column (most flexible for custom content)
Combining Page Templates with Blocks¶
Page templates define layout; blocks define content.
Pattern: Page template wraps blocks
// Example: bullet-list page with callout block
<BulletListSlideTemplate
title="Action Items"
items={[
'Complete hardware installation',
'Update firmware to v2.1',
{ text: 'Schedule training session', highlight: true }
]}
/>
// Example: two-column page with stat-cards block
<TwoColumnSlideTemplate
title="Performance Metrics"
leftContent={<StatCardsBlock cards={[...]} />}
rightContent={<VennChartBlock sets={[...]} />}
/>
Key principle: Page templates accept React.ReactNode - you can pass:
- Block components (recommended)
- Raw JSX/HTML
- Mixed content
Registry¶
Location: src/page-templates/registry.ts
The registry exports:
- PageTemplateId - Union type of all valid page template IDs
- PageTemplateDefinition - Interface for registry entries
- pageTemplateRegistry - Record mapping IDs to definitions
Programmatic access:
import { pageTemplateRegistry } from '../page-templates/registry';
// Get all page template IDs
const availableTemplates = Object.keys(pageTemplateRegistry);
// → ['hero', 'bullet-list', 'two-column', 'timeline']
// Get example props for a template
const heroExample = pageTemplateRegistry['hero'].exampleProps;
Adding a New Page Template¶
Prerequisites:
1. The layout pattern must be reusable across multiple decks
2. Existing page templates cannot express the layout cleanly
3. You have a clear React.FC<ConfigInterface> component
Steps:
-
Create component in
src/shared/design-system/slide-templates/:// MyNewSlideTemplate.tsx export interface MyNewConfig { title: string; // ... other props } export const MyNewSlideTemplate: React.FC<MyNewConfig> = ({ title, ... }) => { return ( <StyledSlide variant="default"> <PageContentFrame title={title}> {/* Your layout */} </PageContentFrame> </StyledSlide> ); }; -
Register in
src/page-templates/registry.ts:import { MyNewSlideTemplate } from '../shared/design-system/slide-templates/MyNewSlideTemplate'; export type PageTemplateId = 'hero' | 'bullet-list' | 'two-column' | 'timeline' | 'my-new'; export const pageTemplateRegistry: Record<PageTemplateId, PageTemplateDefinition> = { // ... existing entries 'my-new': { id: 'my-new', title: 'My New Slide', description: 'Description for AI agents and humans.', component: MyNewSlideTemplate, exampleProps: { title: 'Example Title', // ... other example props } } }; -
Export from
src/page-templates/index.ts:export { pageTemplateRegistry, type PageTemplateId } from './registry'; -
Document in
docs/page-templates.md(this file) with: - Purpose
- Interface
- Props table
- Example
- When to use
-
AI agent guidance
-
Test with
npm run build:update:deck -- <your-test-deck>
Common Patterns¶
Pattern 1: Hero → Content → Timeline¶
Deck structure:
P1: hero (title slide)
P2: bullet-list (key points)
P3: two-column (comparison)
P4: timeline (implementation plan)
Pattern 2: Nesting Blocks in Two-Column¶
<TwoColumnSlideTemplate
title="Technical Specs"
leftContent={
<div>
<h3>Hardware</h3>
<KeyValueTableBlock rows={[...]} />
</div>
}
rightContent={
<div>
<h3>Software</h3>
<BulletListBlock items={[...]} />
</div>
}
/>
Pattern 3: Highlighting Key Points¶
<BulletListSlideTemplate
title="Critical Actions"
items={[
'Review safety protocols',
{ text: 'Complete certification by Friday', highlight: true },
'Submit report to manager'
]}
/>
AI Agent MCP Integration¶
When an AI agent (e.g., WorkBuddy) receives a request to create or modify a deck, it should:
- Read this documentation to understand available page templates
- Check
src/page-templates/registry.tsfor the canonical, up-to-date list - Match intent to page template using the decision tree above
- Validate props against the TypeScript interfaces
- Use example props from registry as starting point
MCP tool usage:
- Use read_file to fetch src/page-templates/registry.ts
- Use read_file to fetch individual slide template implementations
- Use edit_file to update deck intent .md files
- Use execute_command to run npm run build:update:deck after changes
Error prevention:
- Always check that the page template ID exists in pageTemplateRegistry
- Always provide required props (title is required for all templates)
- Always match prop types (TypeScript interfaces are authoritative)
Source Files¶
| File | Purpose |
|---|---|
src/page-templates/registry.ts |
Canonical registry (type definitions, registry object) |
src/page-templates/index.ts |
Public exports |
src/page-templates/README.md |
Developer notes |
src/shared/design-system/slide-templates/*.tsx |
Implementations |
src/shared/design-system/components.tsx |
StyledSlide, PageContentFrame |
docs/page-templates.md |
This documentation |
Related Documentation¶
- Block Styles:
docs/block-library.md(content units that go inside page templates) - Deck Templates:
docs/deck-templates.md(purpose-specific deck configurations) - System-Wide Layout:
docs/system-wide-layout.md(header, footer, content area rules) - Deck Intents:
docs/deck-intents.md(how to define deck structure with page templates)