Skip to main content

Feature: Onboarding Flow (iOS)

Version: 1.1.0 Last Reviewed: 2026-02-10 Status: Approved

User Story

As a first-time user, I am guided through the required setup steps so I can start using the app immediately. As a second caregiver, I can accept an invite and start tracking alongside the primary parent.

MVP Scope

  • Sequential first-launch flow: Server URL → Auth → Add Baby → Dashboard
  • Three auth paths: Create Account, I Have an Invite, Log In
  • Each step reuses screens built for other features
  • Invite path combines account creation with share link acceptance

NOT in MVP

  • Feature walkthrough or tutorial overlays
  • Skip/defer options (all steps required)
  • Social auth (Google, Apple Sign In)
  • Magic link auth (post-MVP #12)

Flow

Step 1: Server URL

┌──────────────────────────┐
│ Baby Basics │
│ │
│ Server URL │
│ ┌─────────────────────┐ │
│ │ https://baby.bretz… │ │ ← Pre-filled from build config
│ └─────────────────────┘ │
│ │
│ ┌─────────────────────┐ │
│ │ Continue │ │
│ └─────────────────────┘ │
│ │
│ Verifies server is │
│ reachable via /health │
└──────────────────────────┘
  • Pre-filled with build config URL (default: https://baby.bretzfam.com)
  • User can edit the URL (for self-hosted instances)
  • "Continue" validates by hitting /api/v1/health
  • If unreachable: show error with retry
  • URL saved to UserDefaults on success

Step 2: Authentication

┌──────────────────────────┐
│ ← Back │
│ │
│ Welcome to Baby Basics │
│ │
│ ┌─────────────────────┐ │
│ │ Create Account │ │ ← Primary button
│ └─────────────────────┘ │
│ ┌─────────────────────┐ │
│ │ I Have an Invite │ │ ← Near-equal button
│ └─────────────────────┘ │
│ │
│ Already have an │
│ account? Log in │ ← Text link
└──────────────────────────┘

Create Account path:

  • Name, Email, and Password fields
  • Name: required, 1-100 characters
  • Password minimum: 8 characters
  • Show/hide password toggle
  • "Create Account" button → POST /auth/register (with name)
  • On success: token saved to Keychain, proceed to Step 3

I Have an Invite path:

  • Name, Email, and Password fields (same as Create Account)
  • Invite code field (the share link token, can paste)
  • "Join" button → POST /auth/register (with name), then POST /invites/accept
  • On success: token saved, invite accepted, skip Step 3 (baby already exists), go to Dashboard
  • Shows confirmation: "You're now tracking Baby Name" with subtext "Shared by Johnny" (from child.name and granted_by.name in accept response)
  • If user already has account: show "Already registered? Log in with your invite" toggle

Log In path:

  • Email + Password fields
  • "Log In" button → POST /auth/login
  • On success: token saved, check if user has children
    • Has children → go to Dashboard
    • No children → go to Step 3

Step 3: Add Baby

┌──────────────────────────┐
│ ← Back │
│ │
│ Add your baby │
│ │
│ Name │
│ ┌─────────────────────┐ │
│ │ │ │
│ └─────────────────────┘ │
│ Date of birth │
│ ┌─────────────────────┐ │
│ │ 📅 Pick date │ │ ← Native date picker
│ └─────────────────────┘ │
│ │
│ ┌─────────────────────┐ │
│ │ Let's Go! │ │
│ └─────────────────────┘ │
└──────────────────────────┘
  • Name field: required, min 1 character
  • Date of birth: native iOS date picker, defaults to today
  • "Let's Go!" → POST /children
  • On success: navigate to Dashboard

Step 4: Dashboard

  • Onboarding complete, normal app flow begins
  • Subsequent launches skip onboarding (token exists in Keychain)

State Management

  • Onboarding progress tracked via AppState
  • States: .serverUrl, .auth, .addBaby, .ready
  • Back button available on Steps 2 and 3
  • If app is killed mid-onboarding, restart from last incomplete step
  • Server URL persists in UserDefaults even if auth isn't complete

Error Handling

  • Server unreachable: "Can't connect to server. Check the URL and try again." + Retry button
  • Registration failed (duplicate email): "An account with this email already exists. Try logging in."
  • Login failed: "Invalid email or password." (generic, no email enumeration)
  • Invalid invite code: "This invite link is invalid or has already been used."
  • Network error: Generic error with retry button

Acceptance Criteria

  • First launch shows server URL configuration screen
  • Server URL is pre-filled from build config
  • Server URL is validated via /health endpoint before proceeding
  • Invalid server URL shows clear error with retry
  • Create Account path: can register with name + email + password
  • I Have an Invite path: can register + accept invite in one flow (shows who shared)
  • Log In path: can log in with existing account
  • After auth, shows "Add your baby" screen (if no children)
  • After adding child, lands on Dashboard ready to use
  • Subsequent launches go directly to Dashboard (skip onboarding)
  • Can go back to previous steps during onboarding
  • Token persists in Keychain across app restarts
  • Invite path skips "Add baby" step (baby already shared)

Test Cases

  1. Full new user flow: Server URL → Register → Add Baby → Dashboard
  2. Invite flow: Server URL → I Have an Invite → Register + code → Dashboard (baby already visible)
  3. Returning user flow: Server URL → Log In → Dashboard (has children)
  4. Returning user, no children: Server URL → Log In → Add Baby → Dashboard
  5. Invalid server URL: Enter bad URL → error message → fix URL → proceed
  6. Duplicate email: Try to register with existing email → error → switch to login
  7. Wrong password: Try to log in with wrong password → error
  8. Invalid invite: Enter expired/used invite code → error
  9. Back navigation: Go to Step 2, go back to Step 1, URL is still filled
  10. Kill and restart: Complete Step 1, kill app, reopen → starts at Step 2 (URL saved)
  11. Subsequent launch: Complete onboarding, close app, reopen → goes to Dashboard

Boundaries

  • No "skip" option - all steps are required
  • No tutorial or feature walkthrough
  • No account deletion during onboarding
  • No deep link handling during onboarding (deferred until after auth)
  • The invite code is the raw token from the share link URL (user can paste from Messages/email)