Meet Coach -- Feature Exploration & PRD
Product: Objectuve (codename: Enkidu) Feature: Meet Coach -- personalized coaching configuration Status: Shipped — May 2026 Date: April 2026
1. Problem Statement
Objectuve has an AI Coach that provides context-aware advice, insight cards, check-in prompts, and milestone suggestions. But right now, users have no idea it exists until they accidentally tap a sparkle icon. And when they do find it, the Coach speaks in exactly one voice -- a hardcoded "coach who's also a friend" tone baked into every LLM prompt in CoachService.
Three problems:
Discovery failure. Coach is arguably Objectuve's most differentiating feature -- a persistent, context-aware advisor. Yet the 5-slide onboarding wizard never mentions it. Users who'd benefit most during their fragile first week don't know it exists.
One-size-fits-none coaching. A competitive athlete wants blunt accountability. Someone managing productivity anxiety wants gentleness. A college student building study habits wants energy and hype. The current fixed prompt is a reasonable middle ground that excels for nobody.
Low engagement ceiling. Without personalization, Coach interactions feel generic. There's no moment where the Coach becomes their coach. This caps the feature's retention potential.
Meet Coach solves all three: introduces Coach during onboarding, lets users shape the coaching relationship, and creates a memorable moment that transforms "the app's AI" into "my Coach."
2. Goals & Success Metrics
Primary Goals
- Introduce Coach to 100% of new users
- Let users personalize coaching across four dimensions: persona, tone, focus area, frequency
- Increase Coach engagement by making the voice feel personal
Success Metrics
| Metric | Target (90 days post-launch) |
|---|---|
| % of active users who've opened Coach modal at least once | 60%+ |
Coach configuration completion rate (from /meet-coach) | 70%+ of users who start |
| Weekly Coach interactions per active user | 2+ per week |
| Daily check-in prompt tap-through rate | 25%+ |
| 7-day retention lift for configured vs. unconfigured users | +10pp |
Guardrails
- Flow must complete in under 90 seconds -- this is an anti-social app; configuration is not the product
- No increase in daily session time from the configuration itself
- Coach preference storage must not increase API latency for non-coach endpoints
3. User Stories
- US-1: As a new user, I want to learn Coach exists during onboarding and optionally configure it, so I get personalized guidance from day one.
- US-2: As a user on Meet Coach, I want to choose from distinct coaching styles with clear examples, so I pick the voice that motivates me.
- US-3: As a user, I want to adjust how supportive vs. demanding Coach is.
- US-4: As a user, I want to set focus priorities (streaks, milestones, reflection, accountability).
- US-5: As a user, I want to control how often Coach reaches out.
- US-6: As a returning user, I want to revisit
/meet-coachfrom Settings to change preferences. - US-7: As an unconfigured user who opens Coach modal, I want a brief nudge to set up preferences.
- US-8: As a configured user, I want advice/insights/check-ins to actually sound different based on my settings.
4. Feature Design
4a. Coaching Personas (The Archetypes)
Each persona represents a different coaching philosophy. Example messages respond to the same scenario: user missed 2 days of a 12-day streak on "Learn Spanish."
The Captain
Tagline: "Clear eyes, steady course." Tone: Calm authority. Concrete language -- numbers, dates, specific actions. Wastes zero words. Default focus: Milestones Example: "Two days off. Your 'Learn Spanish' streak was at 12 before the gap. Rebuild starts with one session today -- even 10 minutes counts toward a new run." Visual: Navy blue (#1e3a5f). Icon: compass.
The Spark
Tagline: "Energy is contagious -- starting now." Tone: High-energy enthusiasm that's specific, not hollow. Celebrates showing up more than outcomes. Default focus: Streaks Example: "Hey, you're back! That 12-day streak on 'Learn Spanish' showed you can build serious momentum. New streak starts today -- what's your first session going to be?" Visual: Bright orange (#f28529). Icon: lightning bolt.
The Mirror
Tagline: "The answer is usually already in your head." Tone: Reflective and question-driven. Rarely tells users what to do; asks questions that surface their own insight. Default focus: Reflection Example: "You had 12 days of consistent work on 'Learn Spanish' before this pause. What changed two days ago -- was it circumstance, or did something about the routine stop working?" Visual: Soft violet (#8b5cf6). Icon: ripple circles.
The Rival
Tagline: "You said you wanted this." Tone: Blunt accountability without cruelty. Treats users as capable adults who made commitments. Default focus: Accountability Example: "Twelve-day streak on 'Learn Spanish' -- gone. The gap happened; dwelling on it won't close it. Log a session today or decide this goal needs a different approach." Visual: Deep red-orange (#dc2626). Icon: target.
The Sage
Tagline: "Progress is a practice, not a performance." Tone: Warm wisdom. Takes the long view. Contextualizes setbacks as normal. Default focus: Reflection Example: "A 12-day streak is evidence that you can sustain effort on 'Learn Spanish.' Two days off doesn't erase that capacity -- it just means today is where you pick the thread back up." Visual: Warm gold (#b8860b). Icon: mountain.
The Analyst
Tagline: "The data tells a story." Tone: Pattern-focused and evidence-driven. References numbers, trends, comparisons. Suggests optimizations. Default focus: Milestones Example: "Your 'Learn Spanish' streak peaked at 12 days -- your longest yet. Looking at your check-in times, you were most consistent on weekday mornings. Worth scheduling today's session for that same window." Visual: Teal (#0d9488). Icon: chart/lens.
4b. Tone Spectrum
Single axis: Supportive <---> Demanding. Independent of persona -- modifies how hard the persona pushes. Stored as integer 1-5.
| Value | Label | Effect |
|---|---|---|
| 1 | Gentle | Lead with what's going well. Frame suggestions as options. |
| 2 | Supportive | Warm and encouraging. Acknowledge effort before suggesting. |
| 3 | Balanced | Direct but kind. Mix encouragement with honest assessment. |
| 4 | Direct | Straightforward, action-oriented. Name problems clearly. |
| 5 | Tough | Blunt. Hold user to stated commitments. No hedging. |
Key insight: At Tone 5, The Spark still sounds like The Spark (energetic, forward-looking), not like The Rival. Persona = character; tone = intensity.
4c. Focus Area Priorities
Users select up to 2 focus areas (first tap = primary, second = secondary):
| Focus Area | What Coach Emphasizes |
|---|---|
| Streaks | Daily consistency, habit formation, showing up |
| Milestones | Progress toward checkpoints, completion rates, next steps |
| Reflection | Patterns, self-awareness, mood-to-progress connections |
| Accountability | Commitments kept/broken, timeline adherence, honest assessment |
Primary area's prompt text included in full; secondary adds shorter supplementary instruction.
4d. Communication Frequency
| Preset | Check-in Prompts | Insight Cards |
|---|---|---|
| Every day | Daily | On every page load |
| When I'm active | Only on sign-in days | On page load |
| When I need it | Only on streak break, milestone overdue, or 3+ days inactive | Only on stalled pages |
| Milestones only | Only on milestone/streak milestones (7, 14, 30) | Celebration-type only |
| Minimal | Never auto-generated | Never; Coach modal only |
GenerateAiCheckInPromptsJob gains a per-user frequency filter before the existing recent_ai_notification? check.
5. UX Flow
5a. First-Time Experience
3 sections on a single scrollable page (not a multi-step wizard). Target: under 60 seconds.
Section 1: Greeting + Persona Selection
- Brief conversational Coach greeting (2-3 sentences, uses
user.firstName) - 6 persona cards in 2-column grid. Each shows: name, tagline, colored icon, truncated example message
- Tap to select; auto-scrolls to next section
Section 2: Tone + Focus
- Tone slider -- 5-point segmented control ("Gentle" through "Tough"). Default: 3. Preview message updates per persona+tone combination (static, not LLM-generated)
- Focus chips -- 4 pill buttons. First tap = primary (filled), second = secondary (outlined). One-line description updates below.
Section 3: Frequency + Confirmation
- Frequency selector -- 5 radio-style cards, vertically stacked
- Confirmation -- glassmorphism summary card showing all selections. "Save Preferences" CTA. "Skip for now" secondary link.
After saving: brief persona-appropriate greeting acknowledging the configuration.
5b. Return Visit (/meet-coach)
Summary view at top showing current configuration (persona card, tone, focus, frequency) with "Edit" affordances per section. "Reset to Defaults" link at bottom. Coach greeting acknowledges the revisit.
5c. Integration Points
Onboarding Wizard: New slide 4 (after Community, before First Goal). Lightweight intro: sparkle icon, "Your Goal Coach" headline, brief body, "Meet Your Coach" CTA (navigates to /meet-coach post-wizard) + skip option. totalSlides bumps from 5 to 6.
Settings Page: "Goal Coach" card added to Profile tab after Dashboard Mode. Shows current persona/tone/frequency. "Customize Coach" links to /meet-coach.
Coach Modal: Unconfigured users see a setup nudge in the welcome message + a suggested prompt chip linking to /meet-coach.
Daily Check-ins: Job reads preferences for frequency filtering and passes them to CoachService for personalized voice.
6. Data Model Changes
Extend UserDetail JSONB (recommended)
UserDetail already has a data JSONB column with store_accessor (see rails_api/app/models/user_detail.rb). Add:
store_accessor :data, :coach_persona # "captain"|"spark"|"mirror"|"rival"|"sage"|"analyst"
store_accessor :data, :coach_tone # 1-5 integer
store_accessor :data, :coach_focus_primary # "streaks"|"milestones"|"reflection"|"accountability"
store_accessor :data, :coach_focus_secondary # same, nullable
store_accessor :data, :coach_frequency # "daily"|"active"|"stuck"|"milestones"|"minimal"
store_accessor :data, :coach_configured_at # ISO 8601 datetimeWhy JSONB over columns on users: Preferences are read as a unit, consumed only by CoachService and frontend display. No individual indexes needed. Avoids migration on the high-traffic users table. UserDetail exists for exactly this.
Convenience method on User:
def coaching_preferences
detail = details || create_details!
{
persona: detail.coach_persona || 'spark',
tone: (detail.coach_tone || 3).to_i,
focus_primary: detail.coach_focus_primary || 'streaks',
focus_secondary: detail.coach_focus_secondary,
frequency: detail.coach_frequency || 'daily',
configured: detail.coach_configured_at.present?
}
endDefaults map to current hardcoded behavior. Zero change for existing users.
GraphQL Changes
- New mutation:
UpdateCoachingPreferences-- accepts persona, tone, focusPrimary, focusSecondary, frequency - New type:
CoachingPreferencesTypenested underUserType - New frontend constant in
ionic_frontend/src/constants/graphql/ai.js
7. How Preferences Affect Coach Behavior
Prompt Preamble Architecture
New private method build_personality_preamble(user) in CoachService constructs a personality block prepended to each method's prompt:
You are a goal coach for Objectuve.
Your coaching persona is: [PERSONA_DESCRIPTION]
Tone calibration: [TONE_MODIFIER]
Focus priorities: [FOCUS_INSTRUCTIONS]
Core rules (always apply):
- 2 sentences max unless asked for more
- Never use motivational cliches
- Never guilt or pressure
- Reference specific goals/streaks/progress when available
- Be action-forward: tell the user what to DO, not how to FEELEach CoachService method gains an optional user: keyword. When absent, existing hardcoded prompt used as-is.
Concrete Examples (same get_advice call, different preferences)
Scenario: "Viewing goal 'Learn Spanish', 42% complete, 5 days left, last update 3 days ago"
- Spark, Tone 2, Focus: Streaks: "You're nearly halfway through 'Learn Spanish' and you've been quiet for three days -- but that 42% is real progress. A quick session today gets your rhythm back."
- Rival, Tone 5, Focus: Accountability: "42% done on 'Learn Spanish' with 5 days left and no activity for 3 days. That math doesn't work unless you hit at least one milestone per day from here."
- Mirror, Tone 1, Focus: Reflection: "Three quiet days on 'Learn Spanish' after steady progress to 42%. What shifted -- was it the goal itself, or did something else pull your attention?"
8. Edge Cases & Open Questions
Edge Cases
| # | Scenario | Resolution |
|---|---|---|
| EC-1 | No UserDetail record | coaching_preferences does find_or_create. Defaults ensure valid inputs. |
| EC-2 | User leaves without saving | Unsaved state lost. Standard behavior. |
| EC-3 | Persona identifier renamed in future | Map retired identifiers to nearest replacement at read time. |
| EC-4 | LLM provider variance | Use explicit behavioral instructions ("ask questions") not abstract adjectives ("be reflective"). Test all providers. |
| EC-5 | The Rival at Tone 5 feels harsh | "Core rules" guardrail (never guilt/pressure) is the safety net. QA must test sensitive scenarios. |
| EC-6 | Persona change mid-conversation | Clear history in useAiCoach.ts when preferences change (method already exists). |
| EC-7 | MockLlm fallback | Update to include persona-aware mock or at minimum not crash with preferences. |
Open Questions
- Live preview vs. static examples on persona cards? Recommend static for MVP -- live adds latency for a screen visited once.
- Default persona for unconfigured users? Recommend The Spark at Tone 3 -- closest to current hardcoded voice.
- XP reward for completing setup? Suggest 50 XP + "Coach's Pick" badge via
UserAction.generate. - Frequency filtering in SQL vs. Ruby? Ruby-level (check each user in loop) is simpler, maintains existing job structure, fine for current scale.
- Offline/Ollama model fidelity? Smaller models may follow persona instructions poorly. Recommend: don't surface provider warnings; let it work as well as each model allows.
9. Implementation Phases
Phase 1: MVP -- "Meet Coach Exists" (1-2 sprints)
Backend:
- Add
store_accessorfields toUserDetail - Add
coaching_preferencesmethod toUser - Create
UpdateCoachingPreferencesmutation +CoachingPreferencesType
Frontend:
- Create
MeetCoach.vuepage at/meet-coach - Add route to router
- Add "Goal Coach" card to Settings Profile tab
- Add GraphQL mutation constant
Coach Integration (minimal):
- Add
build_personality_preambletoCoachService - Modify
get_adviceto acceptuser:and prepend preamble - Update
useAiCoach.tswelcome message for unconfigured users
NOT in Phase 1: Onboarding slide, check-in personalization, insight personalization, XP reward.
Phase 2: Full Personalization (1 sprint)
- Inject preamble into
generate_insight,generate_check_in_prompt,refine_description - Update
GenerateAiCheckInPromptsJobwith frequency filtering + preference passing - Add Coach slide to
OnboardingWizard.vue(new slide 4,totalSlides= 6) - Award "Coach's Pick" badge + 50 XP on configuration
Phase 3: Polish & Measurement (1 sprint)
- Add
UserActionmilestones for coach configuration events - Instrument Coach interactions with persona/tone metadata
- Return-visit state for
/meet-coach(summary view with edit) - QA across all LLM providers
- Consider live tone preview
10. Design Suggestions
Layout: Full-bleed ion-content, bg-secondary/30, content max-w-lg mx-auto, px-5 py-6. Glassmorphism Card components.
Persona Cards: 2-column grid. Unselected: bg-card/50 backdrop-blur-sm border. Selected: border-2 border-primary ring-2 ring-primary/20 with persona accent color left-bar. 48x48 rounded avatar with gradient + Lucide icon.
Tone Slider: 5-segment control (not continuous). Active: bg-primary text-white. Preview card below updates per combination.
Focus Chips: Pill-shaped row. Primary: bg-primary text-white. Secondary: border-primary text-primary bg-primary/10.
Frequency: Vertical radio-card stack. Selected: border-primary bg-primary/10 ring-2 ring-primary/20 + checkmark.
Animations: Staggered pop-in on persona cards. fade-in slide-in-from-bottom on sections. Confetti on save.
Accessibility: role="radiogroup" on persona/frequency. role="slider" on tone. role="checkbox" on focus chips. Accent colors on borders/icons only (not text).
Critical Files
| File | Change |
|---|---|
rails_api/app/models/user_detail.rb | Add coaching preference store_accessors |
rails_api/app/models/user.rb | Add coaching_preferences convenience method |
rails_api/app/services/ai/coach_service.rb | Add build_personality_preamble, modify methods to accept user: |
rails_api/app/graphql/mutations/ | New UpdateCoachingPreferences mutation |
rails_api/app/graphql/types/ | New CoachingPreferencesType |
rails_api/app/jobs/ai_coaching/generate_ai_check_in_prompts_job.rb | Frequency filtering (Phase 2) |
ionic_frontend/src/views/MeetCoach.vue | New standalone page |
ionic_frontend/src/router/index.ts | Add /meet-coach route |
ionic_frontend/src/views/Settings.vue | Add "Goal Coach" card to Profile tab |
ionic_frontend/src/constants/graphql/ai.js | New mutation constant |
ionic_frontend/src/composables/useAiCoach.ts | Preference-aware welcome messages |
ionic_frontend/src/components/onboarding/OnboardingWizard.vue | New Coach slide (Phase 2) |
Related Documentation
- Meet Coach — feature & configuration guide for the shipped implementation
Last updated: 2026-07-15