Recovery App Onboarding Excellence
Build compassionate, effective onboarding experiences for recovery and wellness applications that serve vulnerable populations with dignity and practical utility.
When to Use
✅ USE this skill for:
First-time user onboarding flows Feature discovery and app tours Progressive disclosure design Permission request timing and framing Welcome screens and value propositions Recovery program selection flows Crisis resource integration Privacy and anonymity communication
❌ DO NOT use for:
General mobile responsive design → use mobile-ux-optimizer Marketing/conversion optimization → use seo-visibility-expert Native iOS/Android development → use platform-specific skills Database schema design → use supabase-admin Core Principles 1. Compassion First, Features Second
Recovery users are often in vulnerable states. Every onboarding decision must consider:
❌ ANTI-PATTERN: "Sign up to track your progress!" ✅ CORRECT: "You're taking a brave step. Let's set up a private space for your journey."
❌ ANTI-PATTERN: Requiring account creation before showing any value ✅ CORRECT: Let users explore core features anonymously, then offer accounts for persistence
- Value Before Commitment
Show meaningful value before asking for personal information:
WRONG ORDER: 1. Create account 2. Enter personal details 3. Grant permissions 4. Finally see the app
RIGHT ORDER: 1. Show immediate value (meeting finder, crisis resources) 2. Demonstrate app benefits 3. Offer optional account for saved data 4. Request permissions contextually
- Non-Judgmental Language
Avoid shame-inducing or triggering language:
❌ "How many days since your last relapse?" ✅ "What's your current sobriety date?"
❌ "You failed to complete..." ✅ "No worries—pick up where you left off"
❌ "Are you an alcoholic or drug addict?" ✅ "Which recovery programs interest you?"
Mobile Onboarding UX (2025 Best Practices) Progressive Disclosure
Break complex onboarding into digestible stages:
// ✅ GOOD: Staged onboarding with clear progress const ONBOARDING_STAGES = [ { id: 'welcome', required: false }, // Emotional connection { id: 'programs', required: false }, // Personalization { id: 'features', required: false }, // Value discovery { id: 'preferences', required: false }, // Customization { id: 'safety', required: false }, // Crisis setup ];
// Each stage should be: // - Skippable (never trap users) // - Under 60 seconds to complete // - Visually distinct with progress indicators // - Reversible (can go back)
Permission Priming (28% Higher Grant Rate)
Never request permissions out of context:
// ❌ BAD: Immediate system permission dialog useEffect(() => { requestLocationPermission(); }, []);
// ✅ GOOD: Contextual priming before system dialog function MeetingSearchPrimer() { return (
Find Meetings Near You
To show meetings within walking distance, we need your location. Your location stays on your device.
"Everboarding" - Beyond First Launch
Onboarding isn't a one-time event:
// Feature discovery on first use of each feature
function useFeatureOnboarding(featureId: string) {
const [hasSeenTooltip, setHasSeen] = useLocalStorage(onboard:${featureId}, false);
return { showTooltip: !hasSeenTooltip, dismissTooltip: () => setHasSeen(true), }; }
// Example: First time using gratitude journal function GratitudeJournal() { const { showTooltip, dismissTooltip } = useFeatureOnboarding('gratitude');
return (
<>
{showTooltip && (
Skeleton Loaders, Never Spinners
Recovery users in crisis need immediate feedback:
" isLoading="isLoading">// ❌ BAD: Spinner creates anxiety// ✅ GOOD: Skeleton shows structure immediately
// Skeleton implementation function MeetingCardSkeleton() { return (
Recovery App Feature Categories Essential Features (Showcase First) Meeting Finder - Core utility, immediate value Crisis Resources - Life-saving, always accessible Safety Planning - Personal support network Engagement Features (Second Priority) Daily Check-ins - HALT awareness Recovery Journal - Reflection and growth Gratitude Practice - Positive reinforcement Advanced Features (Discover Over Time) Sobriety Counter - Milestone tracking Community Forum - Peer support Recovery Plan - AI-assisted guidance Online Meetings - Virtual options Feature Card Pattern interface OnboardingFeature { id: string; icon: React.ComponentType; title: string; description: string; highlight: string; // Key benefit (e.g., "24/7 support available") color: string; // Brand color for visual distinction category: 'essential' | 'engagement' | 'advanced'; }
const FEATURES: OnboardingFeature[] = [ { id: 'meetings', icon: MapPin, title: 'Find Meetings Near You', description: 'Search thousands of AA, NA, CMA, SMART, and other recovery meetings.', highlight: '100,000+ meetings nationwide', color: 'bg-blue-500', category: 'essential', }, { id: 'crisis', icon: Phone, title: 'Crisis Resources', description: 'One-tap access to crisis hotlines and emergency support.', highlight: '24/7 support available', color: 'bg-red-500', category: 'essential', }, // ... more features ];
Crisis Resource Integration
Critical: Only 45% of mental health apps include crisis resources. This is non-negotiable for recovery apps.
Always-Visible Crisis Access // Crisis resources should be accessible from EVERY screen function Navigation() { return ( ); }
// Crisis button design
function CrisisButton({ className }: { className?: string }) {
return (
Onboarding Safety Plan Step // Include safety planning in onboarding, but make it optional function SafetyPlanStep() { return (
Your Safety Network
Having support contacts ready can make all the difference. This is optional—you can set this up anytime.
<EmergencyContactInput
label="Emergency Contact"
placeholder="Someone who can help in a crisis"
/>
<SupportPersonInput
label="Support Person"
placeholder="Sponsor, therapist, or trusted friend"
/>
<div className="flex gap-2 mt-6">
<button className="btn-secondary flex-1" onClick={handleSkip}>
Set Up Later
</button>
<button className="btn-primary flex-1" onClick={handleSave}>
Save Contacts
</button>
</div>
</div>
); }
Recovery Program Selection Inclusive Multi-Selection
Support multiple recovery pathways without judgment:
const RECOVERY_PROGRAMS = [ { id: 'aa', name: 'Alcoholics Anonymous', short: 'AA', color: 'bg-blue-500' }, { id: 'na', name: 'Narcotics Anonymous', short: 'NA', color: 'bg-purple-500' }, { id: 'cma', name: 'Crystal Meth Anonymous', short: 'CMA', color: 'bg-pink-500' }, { id: 'smart', name: 'SMART Recovery', short: 'SMART', color: 'bg-green-500' }, { id: 'dharma', name: 'Recovery Dharma', short: 'Dharma', color: 'bg-amber-500' }, { id: 'ha', name: 'Heroin Anonymous', short: 'HA', color: 'bg-red-500' }, { id: 'oa', name: 'Overeaters Anonymous', short: 'OA', color: 'bg-teal-500' }, { id: 'other', name: 'Other/Multiple', short: 'Other', color: 'bg-gray-500' }, ];
// UI should allow multiple selections function ProgramSelection({ selected, onChange }) { return (
Onboarding Flow Architecture State Management interface OnboardingState { currentStep: number; completedSteps: string[]; selectedPrograms: string[]; meetingPreferences: { formats: ('in-person' | 'online' | 'hybrid')[]; days: string[]; times: ('morning' | 'afternoon' | 'evening')[]; }; safetyContacts: { emergency?: string; support?: string; }; skippedSteps: string[]; }
// Persist across sessions
function useOnboardingState() {
return useLocalStorage
Step Navigation function OnboardingWizard() { const [state, setState] = useOnboardingState(); const currentStep = STEPS[state.currentStep];
const goNext = () => { setState(prev => ({ ...prev, currentStep: Math.min(prev.currentStep + 1, STEPS.length - 1), completedSteps: [...prev.completedSteps, currentStep.id], })); };
const goBack = () => { setState(prev => ({ ...prev, currentStep: Math.max(prev.currentStep - 1, 0), })); };
const skip = () => { setState(prev => ({ ...prev, skippedSteps: [...prev.skippedSteps, currentStep.id], })); goNext(); };
return (
<main className="flex-1 p-4">
<CurrentStepComponent {...currentStep} state={state} setState={setState} />
</main>
<footer className="p-4 border-t border-leather-700">
<div className="flex gap-3">
{state.currentStep > 0 && (
<button onClick={goBack} className="btn-secondary flex-1">
Back
</button>
)}
{currentStep.skippable && (
<button onClick={skip} className="btn-text">
Skip
</button>
)}
<button onClick={goNext} className="btn-primary flex-1">
{state.currentStep === STEPS.length - 1 ? 'Get Started' : 'Continue'}
</button>
</div>
</footer>
</div>
); }
Micro-Interactions Entry Animations // Staggered entrance for lists function StaggeredList({ items, renderItem }) { return (
Carousel Navigation
// Swipe gesture support for mobile feature tours
function useSwipeNavigation({ onNext, onPrev, threshold = 50 }) {
const [touchStart, setTouchStart] = useState
const onTouchStart = (e: React.TouchEvent) => { setTouchEnd(null); setTouchStart(e.targetTouches[0].clientX); };
const onTouchMove = (e: React.TouchEvent) => { setTouchEnd(e.targetTouches[0].clientX); };
const onTouchEnd = () => { if (!touchStart || !touchEnd) return; const distance = touchStart - touchEnd; if (distance > threshold) onNext(); if (distance < -threshold) onPrev(); };
return { onTouchStart, onTouchMove, onTouchEnd }; }
Accessibility Requirements WCAG AA Compliance Contrast: 4.5:1 for text < 18px, 3:1 for text >= 18px Touch targets: Minimum 44x44px Focus indicators: Visible outline on all interactive elements Screen readers: Announce step changes with aria-live Reduced Motion @media (prefers-reduced-motion: reduce) { .animate-fade-in-up, .animate-slide-in { animation: none; opacity: 1; transform: none; } }
Testing Checklist Functional Testing All steps can be completed All steps can be skipped Back navigation works Progress persists across sessions Swipe gestures work on mobile Keyboard navigation works Accessibility Testing Screen reader announces step changes All interactive elements have labels Focus order is logical Color contrast meets WCAG AA Touch targets are 44x44px minimum Performance Testing Initial load under 2 seconds Step transitions under 300ms No layout shifts during animations Works offline after first load Emotional Testing Language is non-judgmental Skip options are clear No pressure tactics Crisis resources visible Privacy messaging clear References
See /references/ for detailed guides:
competitor-analysis.md - I Am Sober, Nomo, Sober Grid patterns wellness-patterns.md - Headspace, Calm, Daylio insights crisis-integration.md - Emergency resource best practices
← 返回排行榜