Self Help AI - iOS Mobile App
View on App Store →I developed the full software stack for Self Help AI, an iOS mobile app that integrates user data, function calling & personalization settings to create a ChatBot experience for the purpose of self-help. The end product uses ~30k lines of code across 24 files, and has amassed over 200 App Store downloads since launch.







Core Features
Notification System
Integrated LLM function calls which allows the LLM to set reminders for the user on request:
const AVAILABLE_FUNCTIONS = {scheduleNotification: {name: "scheduleNotification",description: "Schedule a notification for the user",parameters: {type: "object",properties: {title: {type: "string",description: "The title of the notification"},body: {type: "string",description: "The body text of the notification"},timestamp: {type: "string",description: "The ISO timestamp when the notification should be sent"}},required: ["title", "body", "timestamp"]}}};
Integrated User Data
Developed a secure local storage system that collects and manages user data from the onboarding survey to create personalized chat sessions:
// AIManager.tsexport const constructSystemPrompt = (values: Record<string, any>,baseSystemPrompt: string) => {const name = values['First Name'] || 'there';const age = values['Age'] || 'unknown age';const gender = values['Gender'] || 'person';const growthAreas = values['growth_areas'] || [];const badHabits = values['bad_habits'] || [];const relationshipStatus = values['relationship_status'] || 'unspecified';const employmentStatus = values['employment_status'] || 'unspecified';let motivationStylePrompt = 'Maintain a balanced coaching approach';if (values['motivation_style']) {const selectedStyle = MOTIVATION_STYLE_OPTIONS.find(option => option.display === values['motivation_style']);if (selectedStyle) {motivationStylePrompt = selectedStyle.systemPrompt;}}return `You are a personal AI assistant focused on helping userswith their personal growth and development.Here's information about the user:Name: ${name}Age: ${age}Gender: ${gender}Relationship Status: ${relationshipStatus}Employment: ${employmentStatus}Focus areas: ${growthAreas.join(', ')}Bad habits to work on: ${badHabits.join(', ')}Coaching Style Instructions: ${motivationStylePrompt}`;
Guided Exercises & Lessons
Custom chats for the purpose of achieving specific goals:
const EXERCISE_OPTIONS: Exercise[] = [{id: ' ',title: 'Improve Focus',description: 'Develop techniques to enhance concentration and mental clarity',icon: 'brain',},{id: 'procrastination',title: 'Stop Procrastinating',description: 'Break free from delay patterns and build productive habits',icon: 'clock-time-four-outline',},{id: 'stress',title: 'Reduce Stress',description: 'Learn effective strategies to manage and minimize stress',icon: 'meditation',},{id: 'relationships',title: 'Navigate Relationships',description: 'Improve communication and strengthen connections',icon: 'account-group-outline',},{id: 'recipes',title: 'Meal Planning',description: 'Get personalized healthy recipe suggestions and meal plans',icon: 'food-variant',},{id: 'workout',title: 'Work Out Plan',description: 'Create a customized fitness routine for your goals',icon: 'dumbbell',},];
Personalization Settings
Managed data flow from the survey within personalization settings, allowing users to customize their experience:
export const handleSettingsUpdate = (editableSettings: Record<string, any>,setLocalSelectedValues: (values: Record<string, any>) => void,setCurrentSystemPrompt: (prompt: string) => void,setIsEditing: (value: boolean) => void,setIsSettingsOpen: (value: boolean) => void,systemPrompt: string) => {try {const updatedSettings = {...editableSettings,'First Name': editableSettings['First Name'],'Gender': editableSettings['Gender'],'Age': editableSettings['Age'],'growth_areas': editableSettings['growth_areas'] || [],'relationship_status': editableSettings['relationship_status'],'employment_status': editableSettings['employment_status'],'bad_habits': editableSettings['bad_habits'] || []};updateSurveyResponses({'First Name': updatedSettings['First Name'],'Gender': updatedSettings['Gender'],'Age': updatedSettings['Age'],'growth_areas': updatedSettings['growth_areas'],'relationship_status': updatedSettings['relationship_status'],'employment_status': updatedSettings['employment_status'],'bad_habits': updatedSettings['bad_habits']});setLocalSelectedValues(updatedSettings);const newSystemPrompt = AIManager.constructSystemPrompt(updatedSettings, systemPrompt);setCurrentSystemPrompt(newSystemPrompt);setIsEditing(false);setIsSettingsOpen(false);} catch (error) {console.error('Error saving settings:', error);}};
Custom Animations & UI
Custom animations & advanced styling techniques to present with a professional, polished user-interface:
// Transition effectuseEffect(() => {if (isTransitioningOut) {// Stop all floating animationsanimationRefs.current.forEach(anim => anim.stop());animationRefs.current = [];// Start transition animationsbackgroundDots.forEach(dot => {const randomAngle = Math.random() * Math.PI * 2;const distance = Math.max(width, height) * 1.5;const targetX = Math.cos(randomAngle) * distance;const targetY = Math.sin(randomAngle) * distance;const transitionAnimation = Animated.parallel([Animated.timing(dot.x, {toValue: targetX,duration: 1000,useNativeDriver: true,easing: Easing.easeOut,}),Animated.timing(dot.y, {toValue: targetY,duration: 1000,useNativeDriver: true,easing: Easing.easeOut,}),Animated.timing(dot.opacity, {toValue: 0,duration: 800,useNativeDriver: true,})]);animationRefs.current.push(transitionAnimation);transitionAnimation.start();});}}, [isTransitioningOut]);