journeys walkthroughs 01 first launch - fahadahmed/jamaal-app GitHub Wiki
Journey 1 β First launch and onboarding
Status: done β gaps G-01 β¦ G-10 raised, decided and applied (see the gap log, including G-08, closed in Journey 11). The text below is the walkthrough as first written, with the proposals it raised; the decisions are now in the schema, engine and onboarding docs. Register flow F01, screens OB-01 β OB-09 β TD-01. The behaviour is in Onboarding; this page tests it against the schema.
In one line: a new user meets Jamaal, tells it what a normal day looks like, agrees when it may speak, creates one real Task, Habit and Anchor, and lands on a Today that is not empty.
Preconditions: a fresh install, possibly on an account that already has data on another device (G-01). Notifications not yet asked for.
Side effects at first launch (before any screen): the engine seeds one UserSettings row (defaults: 180-minute normal day, 08:00β19:00 working day, midnight rollover, weekends low) and the three default TaskCategory rows (personal, family, work; keyed by presetKey so a second device's duplicates are merged). firstLaunchAt is set once.
OB-01 Meet Jamaal
- Sees: the companion's greeting and the tagline. "Hello. I'm Jamaal. One list, just for today. I'll help you choose what belongs on it β and notice when it's too much." One filled button (Begin).
- Does: taps Begin.
- Writes:
UserSettings.firstLaunchAt(ifnil) β the trial start fallback. - Assumes:
- first launch is detectable β β G-01 (per-device flag re-runs onboarding on a second device);
- trial start survives reinstall β β (
firstLaunchAtsynced; StoreKit's original-download date is the primary source).
OB-02 The idea
- Sees: "One list. Just today." What Jamaal is not (Projects and boards Β· Streaks and guilt) and what it is (One day at a time Β· Planned the night before Β· Kept in your own iCloud). Continue.
- Reads/writes: nothing.
- Copy to respect: Design's current copy says "Tags, labels, filters" and "Everything stays on device", both of which contradict how the app works (categories exist; sync is through iCloud) β see the Claude Design brief Β§3.
OB-03 iCloud check
- Sees: nothing when iCloud is fine (the step is skipped). A plain explanation if not: signed out, restricted, or offline β "Jamaal works without iCloud; your data just won't sync until you sign in." One button to continue.
- Reads: the iCloud account status; whether an existing account's data has synced (a
UserSettingsrow withonboardingCompletedAt). - Does: continues, or (returning account) taps through Welcome back and skips to Today.
- Assumes:
- we can tell iCloud is available β β G-06 (the container identifier is missing, and CloudKit can't be provisioned on a free Personal Team);
- a second device doesn't re-onboard β β G-01.
OB-04 Your normal day
- Sees: "How much is a normal day?" β focused work outside meetings and life admin; a slider from 30 minutes to 6 hours, default 3 hours. "When does your working day usually end?" β default 19:00. The low / medium / high slider for today, with "Weekends get less by default. You can change any day later."
- Does: sets the three values.
- Writes:
UserSettings.mediumDayMinutes,UserSettings.dayEndMinute; an upsert of today'sDayPlanwith onlycapacityset (all planning fields keep their defaults). - Assumes:
- a
DayPlancan exist with only a capacity β β (every field is defaulted;planningCompletedAtisnil); - today's level doesn't overwrite the weekday defaults β β (
weekdayLevelsis separate); - the day's end and start can't contradict β β G-07 (no validation rule).
- a
- Copy to respect: Design's line "I'll learn the real number" promises silent learning. The app only suggests a number from real use later, never changes it itself. Suggested: "A rough guess is fine. I can suggest a better number once I've seen a few weeks."
OB-05 Reminders and evening time
- Sees: "Once at night to plan, once in the morning with your list. Anything else is yours to switch on." The evening planning time (default 20:00) and the morning list time (default 08:00). Allow notifications and Not now.
- Does: picks times; taps Allow (the system prompt appears) or Not now.
- Writes: the times and the permission outcome β β G-02 (today these are per-device preferences, so a second device starts from defaults and every device notifies). Schedules the evening planning notification.
- Assumes:
- denying is safe β β (the in-app banner at planning time,
SY-01, takes over); - the planning time is sensible relative to the day's end β β (independent; defaults are 19:00 and 20:00).
- denying is safe β β (the in-app banner at planning time,
OB-06 Your first task
- Sees: "Something you need to do today." A title field and the three default categories as chips (pre-selecting none), effort chips (optional). Continue.
- Does: types a title; optionally picks a category and an effort.
- Writes: a
TaskItemwithimportance = low,dueDate = today, optionalcategoryandeffortMinutes. - Assumes:
- the categories exist already β β (seeded at first launch; duplicates on a second device merge by
presetKey); - the task will appear on Today β β G-03 (as worded in the current doc, "this week" isn't due today, and a dateless task is backlog);
- the category chips look right β β G-08 (
colorKeyvalues aren't defined).
- the categories exist already β β (seeded at first launch; duplicates on a second device merge by
OB-07 Your first habit
-
Sees: a short list of presets β Qur'an reading, Dhikr, Exercise, Running β and Something else. Choosing one shows its cadence and target in one editable line. Continue.
-
Does: picks a preset and optionally edits its target.
-
Writes: a
Habit(kind,presetKey, schedule), oneHabitTimeWindow(target, optionaleffortMinutes, optional reminder), nothing inHabitEntryyet. -
Assumes:
- presets are defined β β G-04 (no catalogue); proposal below;
- "Something else" is cheap β β G-10 (the full type picker is too heavy here; proposal: a binary daily habit with just a title).
-
Preset catalogue (proposal for G-04). Bundled app data; all use one all-day window; all editable afterwards.
Preset ( presetKey)kindtargetSchedule effortMinutesQur'an reading ( quran)timed15 min daily 15 Dhikr ( dhikr)counted33 daily β Exercise ( exercise)timed30 min 3 times a week 30 Running ( running)timed30 min 3 times a week 30 Something else binary1 daily β The Qur'an and dhikr values are starting suggestions, since you know these practices better than I do.
OB-08 Your first Anchor
- Sees: "Things your life moves around." The types β Prayer times Β· School run Β· Bin night Β· Plant watering Β· Custom β and Not now. Choosing one opens its short form (prayer: location, method, prayers, Isha end; scheduled: days, a named slot, duration).
- Does: picks a type and fills the form, or skips.
- Writes: an
AnchorRule(sourceKey,configData,effortMinutes,placement); the engine immediately generatesAnchorinstances for today and tomorrow. - Assumes:
- generation needs only the rule β β (module 3);
- creating a rule at, say, 21:00 is harmless β β G-05 (today's earlier prayer windows would be generated already closed and finalised as missed on day one);
- prayer times can be computed β β G-09 (no library chosen);
- location and city search are available β β (coarse location prompt only at this point; city search fallback).
- Not now is fine β β (Today's Anchors section explains what Anchors are and offers to add one).
OB-09 Ready
- Sees: "Let's plan tonight. At 20:00 I'll ask how today went and we'll set up tomorrow together." A line about the trial (14 days, everything included). Open my day.
- Writes:
UserSettings.onboardingCompletedAt(G-01); schedules tomorrow's notifications via module 6. - Assumes: the "Tonight, we'll plan tomorrow" card needs no storage β β (derived: shown while
onboardingCompletedAtis on today's logical date and no Night Planning session exists yet).
What Today shows afterwards (TD-01, day 0)
- Capacity slider at the level chosen; the meter reads "0m of 3h" (the first task has no effort unless one was picked, and the engine counts items without a duration as zero).
- Anchors: the rest of today's prayer windows as a grouped row (for example "Salah 0/3 Β· Asr Β· until 17:58"), because generation skips windows already closed (G-05), with their window bars.
- Habits: the chosen habit (for Qur'an reading, "0 of 15 min Β· Begin").
- Tasks: the first task, with its category label.
- A quiet card: "Tonight, we'll plan tomorrow." No companion guidance yet, no wellbeing score ("gathering data").
Data that exists afterwards (end-state check)
| Model | Rows |
|---|---|
UserSettings |
1 (normal day, day end, onboardingCompletedAt, firstLaunchAt) |
TaskCategory |
3 (seeded) |
DayPlan |
1 β today, capacity only |
TaskItem |
1 β low importance, due today |
Habit / HabitTimeWindow |
1 / 1 |
AnchorRule / Anchor |
0β1 / the remaining windows today and tomorrow's |
Everything else (DeferralRecord, WorkSession, HabitEntry, NightPlanningSession, NudgeLog) |
0 |
Every row above is storable with the current schema, except the synced fields the gaps add (onboardingCompletedAt; planningMinute and morningMinute if G-02 is accepted).
Schema and engine changes this journey implies
If the proposals are accepted:
UserSettings.onboardingCompletedAt: Date?(G-01).UserSettings.planningMinute: Int = 1200andmorningMinute: Int = 480, plus a per-device local "send reminders here" switch (G-02).- Engine rule: an Anchor is never generated for a window that ended before the rule's
createdAt(G-05). - A bundled preset catalogue (G-04).
- A documented settings validation:
rolloverMinute < dayStartMinute < dayEndMinute, with at least two hours between start and end (G-07). - Wording fixes for OB-01 to OB-05 and the onboarding doc (first task "today"; "I can suggestβ¦"; the three copy conflicts).
Two items are not schema questions and need a decision outside it: G-06 (when to enrol in the paid developer programme) and the library choice G-09.