Expanded Onboarding Patterns
Expanded Onboarding Patterns
When to Use This Skill
Use this skill when implementing expanded onboarding patterns patterns in your codebase.
How to Use This Skill
- Review the patterns and examples below
- Apply the relevant patterns to your implementation
- Follow the best practices outlined in this skill
Level 1: Quick Reference (Under 500 tokens)
Onboarding State Structure
interface OnboardingState {
userId: string;
currentStep: number;
totalSteps: number;
completedModules: string[];
skippedModules: string[];
pace: 'quick' | 'standard' | 'thorough';
startedAt: Date;
lastActiveAt: Date;
}
const defaultState: OnboardingState = {
userId: '',
currentStep: 0,
totalSteps: 7,
completedModules: [],
skippedModules: [],
pace: 'standard',
startedAt: new Date(),
lastActiveAt: new Date(),
};
Module Structure
interface OnboardingModule {
id: string;
title: string;
description: string;
estimatedMinutes: number;
prerequisites: string[];
exercises: Exercise[];
checkpoints: Checkpoint[];
}
Level 2: Implementation Details (Under 2000 tokens)
Adaptive Pacing Logic
function adjustPace(state: OnboardingState, feedback: UserFeedback): OnboardingState {
let newPace = state.pace;
// Speed up if user is breezing through
if (feedback.completionTime < feedback.estimatedTime * 0.5 &&
feedback.exerciseScore > 90) {
newPace = state.pace === 'thorough' ? 'standard' : 'quick';
}
// Slow down if user is struggling
if (feedback.exerciseScore < 60 || feedback.requestedHelp) {
newPace = state.pace === 'quick' ? 'standard' : 'thorough';
}
return { ...state, pace: newPace };
}
Session Persistence
const STORAGE_KEY = 'onboarding_state';
function saveState(state: OnboardingState): void {
localStorage.setItem(STORAGE_KEY, JSON.stringify({
...state,
lastActiveAt: new Date(),
}));
}
function loadState(): OnboardingState | null {
const saved = localStorage.getItem(STORAGE_KEY);
if (!saved) return null;
const state = JSON.parse(saved);
state.startedAt = new Date(state.startedAt);
state.lastActiveAt = new Date(state.lastActiveAt);
return state;
}
function canResume(state: OnboardingState): boolean {
const hoursSinceActive =
(Date.now() - state.lastActiveAt.getTime()) / (1000 * 60 * 60);
return hoursSinceActive < 72; // 3 days
}
Level 3: Complete Reference (Full tokens)
Complete Onboarding Flow
class OnboardingManager {
private state: OnboardingState;
private modules: OnboardingModule[];
constructor() {
this.state = loadState() || defaultState;
this.modules = loadModules();
}
async startOrResume(): Promise<void> {
if (this.state.currentStep > 0 && canResume(this.state)) {
console.log(`Resuming from step ${this.state.currentStep}`);
} else {
this.state = { ...defaultState, userId: generateUserId() };
}
await this.runCurrentModule();
}
async runCurrentModule(): Promise<void> {
const module = this.modules[this.state.currentStep];
// Check prerequisites
const missingPrereqs = module.prerequisites.filter(
p => !this.state.completedModules.includes(p)
);
if (missingPrereqs.length > 0) {
throw new Error(`Missing prerequisites: ${missingPrereqs.join(', ')}`);
}
// Run module content
for (const exercise of module.exercises) {
const result = await this.runExercise(exercise);
if (!result.passed && this.state.pace === 'thorough') {
await this.provideAdditionalHelp(exercise);
}
}
// Mark complete
this.state.completedModules.push(module.id);
this.state.currentStep++;
saveState(this.state);
}
getProgress(): number {
return (this.state.currentStep / this.state.totalSteps) * 100;
}
}
Best Practices:
- Persist state frequently
- Offer skip options for advanced users
- Provide progress indicators
- Celebrate milestones
- Allow pace adjustment anytime
Success Output
When successfully implementing expanded onboarding patterns:
✅ SKILL COMPLETE: expanded-onboarding-patterns
Completed:
- [x] OnboardingState structure defined with all required fields
- [x] OnboardingModule structure created with exercises and checkpoints
- [x] Adaptive pacing logic implemented (adjustPace function)
- [x] Session persistence enabled (saveState/loadState)
- [x] OnboardingManager class implemented with startOrResume flow
- [x] Progress tracking functional (getProgress method)
Outputs:
- OnboardingState TypeScript interface
- OnboardingModule TypeScript interface
- Adaptive pacing functions
- Session persistence utilities
- Complete OnboardingManager class
Completion Checklist
Before marking this skill as complete, verify:
- OnboardingState includes all required fields (userId, currentStep, totalSteps, completedModules, skippedModules, pace, timestamps)
- OnboardingModule defines prerequisites, exercises, and checkpoints
- Adaptive pacing logic adjusts based on completion time and exercise scores
- Session persistence saves to localStorage with lastActiveAt timestamp
- Resume capability checks if session can be resumed (<72 hours)
- OnboardingManager initializes from saved state or creates new
- Prerequisites validated before running module
- Additional help provided when pace is "thorough" and exercises fail
- Progress calculation returns percentage (0-100%)
Failure Indicators
This skill has FAILED if:
- ❌ OnboardingState missing required fields (userId, pace, timestamps)
- ❌ Pacing logic does not adapt to user feedback (always same pace)
- ❌ Session state not persisted to localStorage after updates
- ❌ Resume logic fails to check 72-hour expiration window
- ❌ Prerequisites not validated before module execution
- ❌ No fallback for missing or invalid saved state
- ❌ Progress percentage calculation incorrect or missing
When NOT to Use
Do NOT use this skill when:
- Building simple linear onboarding (no adaptive pacing needed)
- No session persistence required (single-session only)
- Fixed pace without user feedback adaptation
- No prerequisite dependencies between modules
- Onboarding is single-page form (not multi-step flow)
Use alternatives instead:
- For simple linear flow → Use basic step-by-step component
- For no persistence → Remove localStorage, use React state only
- For fixed pace → Skip adjustPace logic, use constant pace
- For single-page → Use form wizard pattern instead
Anti-Patterns (Avoid)
| Anti-Pattern | Problem | Solution |
|---|---|---|
| Not persisting state | User loses progress on refresh | Call saveState() after every step |
| Ignoring user feedback | Pace never adjusts, poor UX | Implement adjustPace with score/time analysis |
| Skipping prerequisite checks | User sees module before ready | Validate prerequisites in runCurrentModule |
| No resume capability | User must restart every time | Implement canResume and loadState |
| Fixed totalSteps hardcoded | Can't add/remove modules flexibly | Calculate from modules.length dynamically |
| Missing lastActiveAt updates | Can't determine session freshness | Update lastActiveAt on every saveState |
Principles
This skill embodies CODITECT automation principles:
- #1 Recycle → Extend → Re-Use → Create - Reuses OnboardingState and OnboardingModule interfaces across all onboarding implementations
- #2 First Principles - Understands WHY adaptive pacing matters (user retention and comprehension)
- #4 Keep It Simple - Provides clear state structure and simple pacing heuristics
- #5 Eliminate Ambiguity - Explicit pace values ('quick'|'standard'|'thorough') eliminate interpretation
- #6 Clear, Understandable, Explainable - Three-level progressive disclosure makes patterns accessible
- #8 No Assumptions - Validates prerequisites and checks session freshness before proceeding
Full Standard: CODITECT-STANDARD-AUTOMATION.md