Case Study
TheCoverStory
A daily cognitive exercise routine disguised as a family English game. If he ever suspected it was treatment, he'd stop playing.
Role
Solo Designer & Developer
Platform
Mobile Web
Audience
Family (Dad, daily)
Type
Personal Project



The Challenge
The apps that could help him are the ones he'd never open
My dad needed to exercise his mind. But the apps that exist for that in Korea are overwhelmingly clinical, research-branded, and aimed directly at older adults who already suspect something is wrong. They feel like a diagnosis before you've even started. The target audience is forced to face the possibility of dementia on the opening screen.
My dad runs away from that kind of thing. He won't engage with anything that implies he's struggling, not out of stubbornness, but because confronting it feels like admitting defeat. The apps designed to help people like him are precisely the apps he would never open.
So the design problem wasn't cognitive exercise. It was disguise. The app needed to train the right things, and screen for early decline in the background, without ever presenting itself as something medical. He had to want to open it every single day without knowing exactly why it was built.
The clinical stakes are real. The K-MMSE (Korean Mini-Mental State Examination) is the standard tool Korean physicians use to screen for early cognitive decline. The orientation domain (knowing today's year, month, date, day of week, and season) is the first thing to slip in pre-Alzheimer's. It deteriorates before memory. Before language. Before anything you'd notice in daily life. Every game in this app maps to a domain the K-MMSE measures. He just thinks he's playing.

The cover story
Seven game tiles, each one feels like a learning activity. The clinical layer is invisible.
Leaderboard hook
Daily points in the header reset every day. His family's scores are always one tap away on the Scoreboard.
Bottom nav
Three destinations (Scores, Home, Progress), all reachable within thumb distance. Home sits center and raised.
My Role
End to end: concept, design, code, and clinical game mapping
I designed and built this end to end: concept, design, full-stack development, and clinical game mapping. This isn't a spec someone else shipped. Every interaction, every game mechanic, and every data point in the backend was a design decision I made and then built myself.
The constraint that shaped everything: it had to work for my parents without any onboarding, tutorial, or support. If they needed help, the design had failed.
Approach
He thinks he's practicing English and competing against the family
That framing gives him a goal he genuinely cares about: staying sharp, keeping up with family, beating his wife on the leaderboard. The English learning surface (weekly vocabulary topics, translation quizzes, word lists) isn't decoration. It's the entire reason he opens the app.
Meanwhile, each session is quietly generating a behavioral profile: how quickly he orients to today's date, whether serial subtraction accuracy is holding, how his delayed recall compares week over week. The screening happens in the background. He never sees a score on that axis, only his leaderboard rank.
Designing the cover story meant asking: what would a real learning app show? What would make a proud, competitive person feel like they're making real progress? The design had to be convincing enough that the therapeutic layer stayed completely invisible.
Seven games, seven clinical targets
Each game maps directly to a domain in the K-MMSE
The 날짜 퀴즈 (Date Quiz) asks year, month, date, day of week, season, and time of day. These are six of the ten orientation items the K-MMSE tests, and they are the single most sensitive early Alzheimer's signal.
The 수학 대결 (Serial Subtraction) is the exact task from the K-MMSE: start from a number and subtract in fixed steps. It tests working memory and sustained attention, not arithmetic skill. 기억력 게임 (Memory Game) mirrors the registration and delayed recall tasks: five words presented, then tested after two other activities create interference. The rest cover semantic categorization, sentence sequencing, visuospatial tracing, and verbal recall.

K-MMSE calculation task
Serial 7s and 3s, the exact task from the exam. Each answer has to be held in mind while computing the next.
Cover story
Framed as a math duel against family. Competitive framing drives daily return, not clinical obligation.
Timer pressure
Tighter time limits at higher levels stress sustained attention, the same cognitive load the K-MMSE targets.
All seven games
A language toggle adds three more Korean-specific games, bringing the total to ten
None of them announce what they're measuring. In Korean mode the English vocabulary games swap for 단어 유창성 (word fluency by category), 속담 완성 (proverb completion), and 물건 이름 대기 (object naming from description). Each targets a different domain of the same clinical framework.

날짜 퀴즈
Date Quiz
Year · month · date · day of week · season · time of day. Six of the ten K-MMSE orientation items. The first domain to decline in early Alzheimer's.

수학 대결
Serial Subtraction
Serial 7s and 3s, the exact calculation task from the K-MMSE. Each answer has to be held in mind while computing the next, which stresses short-term working memory.

기억력 게임
Memory Game
Five words presented, then tested after two other activities have created semantic interference. Distractors come from the same vocabulary theme, which makes the recall harder and more clinically meaningful.

영어 공부
Vocab Quiz
Word-object association across 14 weekly themes. The cover story that makes everything else believable. Difficulty scales with vocabulary tier as level increases.

문장 맞추기
Sentence Builder
Arrange English words into a grammatically correct sentence. It requires holding multiple chunks in working memory and applying language rules: executive function under mild cognitive load.

글씨 연습
Letter Tracing
Trace Korean and English characters on a pressure-sensitive canvas. It maps to the K-MMSE visuospatial task and exercises fine motor coordination and psychomotor speed.

다른 하나 찾기
Odd One Out
Four words, one from a different category. It tests abstract reasoning and semantic memory: the ability to extract rules from examples, not just recall them.
The Duolingo problem
Serving two masters at once
The hardest tradeoff: to keep the cover convincing, I had to add enough English learning content to make it feel like a real tool. Some games lean more vocabulary drill than I wanted: content that served the story more than the cognitive goals.
Every decision lived in that tension: convincing enough to maintain the disguise, therapeutically dense enough to actually matter. Serving two masters at once: that constraint defined every design choice in the product.
A language toggle in Settings unlocked a second game set. The four language-neutral cognitive games always appear: 수학 대결, 날짜 퀴즈, 글씨 연습, 다른 하나 찾기. In English mode the remaining three are vocabulary games. In Korean mode they swap for 단어 유창성, 속담 완성, and 물건 이름 대기, each targeting a different domain of the same clinical framework. Ten games total, seven visible at once.
This directly resolved the Duolingo problem. The English learning surface became optional, not load-bearing. Dad can switch to the Korean set, which is frankly harder, and the app stays therapeutically complete. The cover story now adapts to the player, not the other way around.
Scoring & Leveling
Two parallel number systems serve completely different purposes
Daily points reset every day and drive the family leaderboard, the competitive surface. Dad loses his lead if he doesn't play. Completing three games earns that day's points. Three, not two, because two might be a warmup.
XP never resets. It's cumulative, and it determines level, which determines game difficulty. Each activity awards 14 to 71 XP on a quadratic curve. Scoring zero still earns 14, so he always makes progress.
Level governs difficulty invisibly: harder vocabulary tiers, bigger serial subtraction numbers, more memory words, tighter time limits. He doesn't see a difficulty setting. He just notices the games feel different as he levels up.

Daily leaderboard
Points reset every day. He loses his lead if he skips, the mechanic that makes the habit self-reinforcing.
Progress chips
0 / 3 games completed today. Completing three unlocks the day's full points. Three, not two, because two might still be a warmup.
Why the streak had to be offline-safe
If the streak breaks because of a spotty connection, the habit breaks too
The streak is the highest-stakes number in the app. Miss a day and it resets. That's the mechanic. But if the streak breaks because Supabase was slow over home wifi, not because he actually missed a day, the trust is gone.
The backend writes to localStorage first and Supabase second for every streak update and session save. If the network fails, the local state is authoritative. The next time connectivity is restored, local data syncs back up automatically, using the higher streak value as the source of truth.
How the Backend Works
localStorage-first writes, optimistic locks on XP
Two Supabase tables: daily_sessions (one row per user per day: scores, completed activities, daily points) and user_progress (cumulative XP, level, streak). The leaderboard polls daily_sessions every 10 seconds, so when mom finishes a game, dad sees it within seconds.
Two design decisions made the backend feel trustworthy: writes go to localStorage first so the app works offline, and XP uses an optimistic lock so a network retry can never award the same points twice.
export const updateStreak = async (userId) => {
const today = getTodayDate();
// Step 1: read best available prior state
const local = readLocalStreak(userId);
let curStreak = local?.currentStreak ?? 0;
let longStreak = local?.longestStreak ?? 0;
// Step 2: compute new streak
const { currentStreak, longestStreak } =
computeStreak(local?.lastActivityDate,
curStreak, longStreak, today);
// Step 3: always write locally, works offline
writeLocalStreak(userId, {
currentStreak, longestStreak,
lastActivityDate: today,
});
// Step 4: best-effort Supabase sync
if (!isSupabaseConfigured()) return;
try {
await updateUserProgress(userId, {
current_streak: currentStreak,
longest_streak: longestStreak,
last_activity_date: today,
});
} catch (err) {
// local state preserved, will sync next session
console.warn('Supabase sync failed', err.message);
}
};export const recordActivityXp = async (
userId, activityPoints
) => {
const gain = computeXpGain(activityPoints);
const prog = await ensureUserProgressRow(userId);
const curXp = prog.xp ?? 0;
const newXp = curXp + gain;
const newLevel = xpToLevel(newXp);
// Optimistic lock: only succeeds if XP unchanged.
// If a retry already ran, 0 rows match → no double-count.
const { data } = await supabase
.from('user_progress')
.update({ xp: newXp, level: newLevel })
.eq('user_id', userId)
.eq('xp', curXp) // ← the lock
.select('xp, level')
.maybeSingle();
if (data) return { gain, xp: data.xp, level: data.level };
// 0 rows matched: XP already updated. Re-read, award 0.
const { data: latest } = await supabase
.from('user_progress')
.select('xp, level')
.eq('user_id', userId)
.single();
return { gain: 0, xp: latest.xp, level: latest.level };
};Design Iterations
The version that shipped wasn't the first idea
Desktop first, camera-assisted
The first version was desktop and iPad-first. The thinking: a wider viewport gives the 글씨 연습 game more room, and MediaPipe hand tracking let you trace letters in mid-air with your finger.
It lasted 15 minutes. Hand tracking ran at ~12fps and was exhausting to use. But the real problem was the premise: my dad doesn't open his laptop or iPad every day.


Dark, professional, wrong signals
Even after moving to mobile, the design used dark navy with plain white tiles and emoji icons. It looked like a well-built productivity tool. That was the problem.
Dark themes signal "tool." Cream and pastels signal "game." We rebuilt the entire visual layer: warm off-white, seven pastel gradients, Lucide icons replacing every emoji.


The grid game no one wanted to tap
규칙으로 집까지 was a 7×7 Korean syllable path game. The cognitive target was solid, but the interaction was not.
A 7×7 grid gives each cell ~40×40px, under the 44px touch minimum. My parents avoided it. I redesigned it, then replaced it with 날짜 퀴즈.

Design Decisions
Seven choices that defined the product
From dark navy to cream
The first version used a dark navy palette: serious, app-like, clinical. The problem is that clinical is exactly what I was trying to avoid. Dark themes signal "tool." Cream and pastels signal "game." I rebuilt the entire visual layer from scratch with a custom design system: warm off-white background, seven distinct pastel gradients (one per game tile), soft shadows, and generous radii. The visual language has to read as a game before a single word is processed.
Mobile-first, not mobile-adapted
This app will be used exclusively on a smartphone, probably one-handed, probably at a kitchen table. Every interactive target is at minimum 44×44px. The bottom navigation pattern (Scores · Home · Progress) keeps primary actions within thumb reach without stretching. Safe-area insets handle notched phones correctly. The home button sits raised in the center of the nav bar, elevated and prominent, because it's the action he'll take most.
Icons, not emojis
The first version used emoji throughout: medals, icons, completion screens. Emojis render inconsistently across Android/iOS versions and OS themes, and they can't be styled. I replaced every emoji with Lucide SVG icons. They keep a consistent stroke weight, scale cleanly, take a theme, and look professional enough to not tip the hand that this is a "cute family app" rather than a real product.
No tutorial
If a 65-year-old needs a tutorial to figure out how to start a game, the design failed. Every game intro screen shows exactly one thing: what the game is, and a large start button. The rules are communicated through the first two questions of play. No modals. No walkthroughs. No help text that will be ignored.
Language mode: two sets, one toggle
Settings holds a single toggle: 영어 or 한국어. It swaps the three language-specific games without touching anything else. This made the English learning surface optional. Dad can run the Korean set entirely and the clinical layer stays complete. The cover story stopped being mandatory the moment it became a choice.
Accessibility as display preference
Settings offers four switches: bigger text, bolder text, high contrast, and reduced motion. None is labeled "for older users" or "accessibility." They're just display preferences, because that's how they should feel to someone who might actually use them. If the label implies a need, the need becomes a reason not to turn it on.
Level lock
XP accumulates and difficulty scales up invisibly, until the games feel too hard. A single toggle (난이도 고정) freezes difficulty at whatever level feels right. Dad doesn't have to explain why. He doesn't have to admit a game got too hard. He just turns it on, and the scaling stops. The clinical data keeps coming in at the same difficulty, and the habit stays intact.



XP never resets
Cumulative XP determines level and difficulty. Scoring zero still earns 14 XP, so he always makes progress.
Level lock (난이도 고정)
One toggle freezes difficulty without admitting it got hard. Clinical data keeps flowing at a consistent level.
Streak counter
Written to localStorage before Supabase, so it survives network failures and a spotty connection never breaks the habit.
Impact at a glance
Dad plays every day. Not because he has to, but because he doesn't want to fall behind.
Daily habit
Structured cognitive exercise every single day, on his own initiative, without it feeling like anything other than a game.
Zero onboarding
No tutorial, no walkthrough, no help text. My parents opened the app and started playing. If they'd needed help, the design had failed.
7 → 10 games
A language toggle added three Korean-specific cognitive games, making the therapeutic layer independent of the English learning cover story.
Outcome
The metric that matters
Mom and dad love it. Dad plays every day, not because anyone told him to, but because he doesn't want to lose his streak or fall behind on the leaderboard. He's doing structured cognitive exercises daily, on his own initiative, without it feeling like anything other than a game.
That's the metric that matters. Not activation rates or session length. Just: did he play today?

with love, THE favorite daughter


