Content Development Guide
How to create training lessons, quizzes, and courses using the reusable component library
Implementation: packages/ui/src/components/training/
This guide covers how to develop training content using the reusable component library.
Quick Start
// Minimal lesson structure
import { LessonContainer, Callout, KeyTakeaways } from '@repo/ui'
import { Stack, Text } from '@mantine/core'
export default function Lesson01Introduction() {
return (
<LessonContainer
title="Introduction"
subtitle="Getting started with the platform"
duration="10 min"
>
<Stack>
<Text>Your lesson content here...</Text>
<Callout type="info" title="What you'll learn">
<Text>- First topic</Text>
<Text>- Second topic</Text>
</Callout>
<KeyTakeaways items={[
'First key point',
'Second key point'
]} />
</Stack>
</LessonContainer>
)
}Note: Stack uses gap="md" by default from the theme (componentThemes.tsx). Do not override this in lessons.
Component Library Overview
See Training Component Reference for complete component documentation with props and examples.
Layout Components
- LessonContainer - Wrapper with header, navigation, mark complete
- LessonContent - Styled content area with proper spacing
Content Highlight Components
- Callout - Info/warning/tip/danger boxes (4 types)
- QuickFact - Single-line highlight for facts
- KeyTakeaways - Summary box for lesson conclusions
Visual Content Components
- SectionHeader - Section divider with icon and gradient (built-in spacing)
- FeatureCard - Card for highlighting features with icon
- ConceptGrid - Grid layout for related concepts
- StepCard - Numbered step for procedural content
- ProcessTimeline - Vertical timeline for sequential processes
Code Components
- CodeBlock - Syntax-highlighted code with copy button
Progress Components
- ProgressRing - Circular progress indicator
- LessonNavigation - Prev/next and progress bar (auto-included)
Quiz Components
- LessonQuiz - Modal quiz for end-of-lesson checks (100% pass required)
- AssessmentQuiz - Full-page assessment for certifications (80% pass default)
Lesson Structure Pattern
Follow this structure for consistent lessons:
import {
LessonContainer,
Callout,
KeyTakeaways,
SectionHeader
} from '@repo/ui'
import { Text, Stack } from '@mantine/core'
import { TrainingConceptGrid } from '@/features/training/components'
import { IconTopic } from '@tabler/icons-react'
export default function Lesson01TopicName() {
return (
<LessonContainer
title="Topic Name"
subtitle="Description of what this covers"
duration="10 min"
>
<Stack>
{/* 1. Introduction */}
<Text size="lg">
Opening paragraph that sets context and hooks the learner.
</Text>
{/* 2. Learning objectives */}
<Callout type="info" title="What you'll learn">
<Stack gap="xs">
<Text>- First learning objective</Text>
<Text>- Second learning objective</Text>
<Text>- Third learning objective</Text>
</Stack>
</Callout>
{/* 3. Main content sections */}
<SectionHeader icon={IconTopic} title="Section One" />
<Text>Content for section one...</Text>
<SectionHeader icon={IconTopic} title="Section Two" />
<Text>Content for section two...</Text>
{/* 4. Key takeaways */}
<KeyTakeaways
items={[
'First key point',
'Second key point',
'Third key point'
]}
/>
{/* 5. Transition to next lesson */}
<Callout type="info" title="Next Up">
In the next lesson, we'll explore...
</Callout>
</Stack>
</LessonContainer>
)
}Spacing Standards:
Stackuses theme defaultgap="md"- do not overrideSectionHeaderhas built-in margins (mt="xl",mb="md") - do not add extra spacingListcomponents don't needmtprops - Stack gap handles spacing- Only use
gap="xs"inside Callouts for tightly grouped items
Quiz File Pattern
Each lesson quiz is a separate file:
// Lesson01TopicQuiz.tsx
import { LessonQuiz, type QuizQuestion } from '@repo/ui'
const questions: QuizQuestion[] = [
{
id: 'q1',
question: 'Question text here?',
options: [
{ value: 'a', label: 'Option A' },
{ value: 'b', label: 'Option B' },
{ value: 'c', label: 'Option C' },
{ value: 'd', label: 'Option D' }
],
correctAnswer: 'b'
}
// Add 3-5 questions per quiz
]
// Export for course.config.ts
export const lesson01TopicQuizConfig = { questions }
interface Props {
onComplete?: (answers: Record<string, unknown>, score: number) => void
onContinue?: () => void
}
export default function Lesson01TopicQuiz({ onComplete, onContinue }: Props) {
return (
<LessonQuiz
questions={questions}
onComplete={(answers, score) => onComplete?.(answers, score)}
onContinue={onContinue}
/>
)
}Course Configuration
Register lessons in course.config.ts:
import type { CourseConfig } from '../../types'
// Lesson imports
import Lesson01Topic from './Lesson01Topic'
import Lesson02Topic from './Lesson02Topic'
// Quiz imports
import Lesson01TopicQuiz, { lesson01TopicQuizConfig } from './Lesson01TopicQuiz'
import Lesson02TopicQuiz, { lesson02TopicQuizConfig } from './Lesson02TopicQuiz'
// Final assessment (if certified)
import FinalAssessment, { finalAssessmentConfig } from './FinalAssessment'
export const myCourse: CourseConfig = {
slug: 'my-course',
title: 'My Course',
description: 'Course description for catalog.',
audience: 'customer', // 'internal' | 'developer' | 'customer' | 'public' | 'partner'
estimatedDuration: '60 min',
lessons: [
{
slug: 'topic-one',
title: 'Topic One',
description: 'What this lesson covers.',
duration: '10 min',
order: 1,
component: Lesson01Topic,
quiz: {
passingScore: 100,
questions: lesson01TopicQuizConfig.questions,
component: Lesson01TopicQuiz
}
},
{
slug: 'topic-two',
title: 'Topic Two',
description: 'What this lesson covers.',
duration: '15 min',
order: 2,
component: Lesson02Topic,
quiz: {
passingScore: 100,
questions: lesson02TopicQuizConfig.questions,
component: Lesson02TopicQuiz
}
}
],
assessments: [
{
slug: 'final-assessment',
title: 'Course Certification',
passingScore: 80,
questions: finalAssessmentConfig.questions,
component: FinalAssessment
}
],
certification: {
certificationSlug: 'my-course-certified',
requiredLessons: 'all',
requiredAssessments: [{ slug: 'final-assessment', minScore: 80 }]
}
}File Structure
apps/command-center/src/features/training/content/courses/{slug}/
├── course.config.ts # Course metadata and lesson registry
├── Lesson01TopicName.tsx # Lesson content component
├── Lesson01TopicNameQuiz.tsx # Inline quiz for lesson
├── Lesson02TopicName.tsx
├── Lesson02TopicNameQuiz.tsx
├── FinalAssessment.tsx # Final certification assessment (optional)
└── PlaceholderLesson.tsx # Placeholder for courses in developmentBest Practices
Content Guidelines
- Keep lessons focused - One concept per lesson, 8-15 minutes reading time
- Start with context - Opening paragraph explains why this matters
- Use visuals - ConceptGrid, FeatureCard, and diagrams break up text
- End with takeaways - KeyTakeaways summarizes key points
- Preview next lesson - Callout at end creates continuity
Quiz Guidelines
- 3-5 questions per lesson - Tests understanding, not memorization
- Clear correct answers - Avoid trick questions or ambiguous options
- Test key concepts - Questions should cover KeyTakeaways content
Passing Score Standards:
- Lesson quizzes: 100% - Users must answer all questions correctly to proceed
- Final assessments: 80% - Required for certification
Accessibility
- Alt text for images - Describe what the image shows
- Semantic headings - Use proper heading hierarchy (h2, h3, h4)
- Color not sole indicator - Don't rely only on color to convey meaning
- Readable font sizes - LessonContent provides proper sizing
Related Documentation
- Training Component Reference - Complete component docs with props and examples
- Course Catalog - All available courses
- LMS Features - Full LMS architecture
- Training Overview - Feature infrastructure
Last Updated: 2026-02-14