Mellow MVP Technical Blueprint — Synthesized Architecture from EdTech, Accessibility, and AI Feedback Research
Mellow MVP Technical Blueprint — Synthesized Architecture from EdTech, Accessibility, and AI Feedback Research
Product: Mellow | Date: 2026-03-20 | Tags: architecture, react-native, expo, fastify, drizzle, postgresql, accessibility, autism, claude-api, azure-speech, fsrs, pix, stripe
Executive Summary
This blueprint synthesizes three prior Mellow research reports into a single, implementable architecture for the MVP. Mellow is a language learning app for autistic adults — the first app at the intersection of neurodivergent accessibility and English learning. The stack is Expo (React Native) + Expo Router for mobile, Fastify 5 + Drizzle ORM + PostgreSQL for backend, Claude Haiku 4.5 for AI feedback, Azure Speech for pronunciation assessment, and Stripe + Pix for payments.
Should Moklabs build this? YES. Brazil has 2.4 million diagnosed autistic individuals (6.9 million estimated including undiagnosed) [IBGE Census 2022, Tismoo]. The global language learning app market reaches $7.36 billion in 2025 growing at 16.15% CAGR [Business Research Insights]. No app exists for this intersection. Even a 0.1% capture of the estimated neurodivergent language-learning population in Brazil represents 6,900+ users at R$19.90/mo = R$137K/mo revenue potential.
0. Strategic Go/No-Go Assessment
Should Moklabs build this?
GO — with the following reasoning:
-
Market white space is real. No language learning app targets autistic adults. Duolingo (185M MAU, $230M Q1 2025 revenue) uses gamification patterns fundamentally hostile to autistic users — time pressure, streak guilt, competitive leaderboards [Duolingo Q3 2025 Shareholder Letter]. Babbel ($352M revenue 2024) focuses on structured lessons but lacks accessibility features [Business of Apps]. Neither offers sensory controls, energy-based session adaptation, or autism-friendly feedback.
-
Addressable population is substantial. Brazil: 2.4M diagnosed ASD (1.2% of population), estimated 6.9M total [IBGE Census 2022, Tismoo/CDC]. Globally, 15-20% of the population is neurodivergent [Neurodiversity Directory]. English proficiency is a career requirement in Brazil’s tech sector, where autistic adults are increasingly employed.
-
Technical stack is validated. Expo powers 2,262+ production apps [Evan Bacon, 2026]. Performance gap vs bare React Native is <5% [Meta Design Solutions, 2026]. FSRS algorithm shows 99.6% superiority over SM-2 in benchmarks across 350M+ reviews [open-spaced-repetition].
-
Cost structure enables profitability. API costs of $0.66/user/mo vs R$19.90 (~$3.80) subscription = 83% gross margin from day one.
What specifically would we build?
A mobile app (iOS + Android via Expo) for Brazilian autistic adults learning English, with:
- Sensory control system (theme, motion, audio, haptics, font)
- Energy-based session adaptation (no guilt, no streaks)
- AI feedback via Claude Haiku 4.5 (explicit, concrete, autism-tuned)
- FSRS-based spaced repetition (local-first)
- Speaking practice via Azure Speech pronunciation assessment
- Pix + Stripe payments
Who buys it and for how much?
ICP: Brazilian autistic adults (18-45) learning English for career advancement, particularly in tech. Secondary: parents/caregivers purchasing for young adults.
Pricing: R$19.90/mo (Plus), R$149.90/yr. Free tier with 1 lesson/day. This is 60% below Duolingo Super (R$49.90/mo in Brazil) and aligned with Brazilian EdTech price sensitivity.
Willingness to pay: High. The autism community in Brazil actively seeks specialized tools. Parents routinely pay R$200-500/mo for therapy and support services. R$19.90 is accessible.
What’s the unfair advantage?
- First-mover in autism x language learning. No competitor exists in this intersection.
- Deep domain expertise. Mellow’s feedback system is designed with autistic communication patterns (no sarcasm, no figurative language, explicit correction format).
- Cost moat. Prompt caching + local-first FSRS keeps API costs at $0.35-0.66/user/mo, making the R$19.90 price point sustainably profitable.
What kills this idea? (Top 3 Risks)
| Risk | Severity | Mitigation |
|---|---|---|
| Small niche, hard to grow beyond autism market | High | Design for autism-first but accessible to all; “calm learning” appeals to broader anxiety/ADHD audiences. 15-20% of population is neurodivergent. |
| Content quality at A1 level requires linguistic expertise | Medium | Co-design with autistic beta testers + hire Portuguese-English linguist for seed content. Budget R$5K for initial 3 packs. |
| Duolingo adds accessibility features | Medium | Duolingo’s gamification-first architecture (streaks, XP, leaderboards) is structurally incompatible with autism-friendly design. Retrofitting would require redesigning core engagement loops. |
1. Competitive Architecture Comparison
How Duolingo, Babbel, and Busuu Build — and Why Mellow Differs
| Dimension | Duolingo | Babbel | Busuu | Mellow |
|---|---|---|---|---|
| Frontend | Native iOS (Swift) + Android (Kotlin), React web [Duolingo Engineering] | Native iOS + Android | Native + web | Expo (React Native) — cross-platform from single codebase |
| Backend | Python + Java microservices on AWS, DynamoDB [Duolingo Engineering Blog] | Ruby on Rails (legacy) + microservices | Node.js | Fastify 5 + PostgreSQL — monolith-first for MVP speed |
| AI/ML | Birdbrain (custom ML for exercise difficulty), GPT-4 for Duolingo Max | Limited AI, rule-based | AI learning paths | Claude Haiku 4.5 for feedback + Azure Speech for pronunciation |
| SRS | Custom spaced repetition (Half-Life Regression) | Proprietary review system | Proprietary | FSRS (open, 20-30% fewer reviews than SM-2 for same retention) |
| Accessibility | Basic VoiceOver/TalkBack support, high-contrast mode | Standard a11y | Standard a11y | Full sensory control system (theme, motion, audio, haptics, font, energy adaptation) |
| Engagement model | Streaks, XP, leaderboards, hearts (punitive) | Completion tracking | Community corrections | No-guilt, energy-aware (no streaks, no competition, effort-based encouragement) |
| Users | 185M MAU, 50M DAU [Q3 2025] | 16M users | 120M registered | Target: 1K beta users by Q2 2026 |
| Revenue | $230M/quarter [Q1 2025] | $352M/year [2024] | ~$45M/year [2024] | Target: R$50K MRR by month 6 |
| Pricing | Free + $7.99-13.99/mo Super | $6.95-13.95/mo (no free tier) | Free + $5.95-13.95/mo | Free + R$19.90/mo (~$3.80) |
Key Architectural Insight
Duolingo uses Kotlin Multiplatform + SwiftUI for mobile and has pioneered native-first development for 100M+ MAU scale. At Mellow’s stage (0 to 1K users), this is overengineering. Expo provides the right abstraction: cross-platform from a single TypeScript codebase, with <5% performance overhead vs native [Meta Design Solutions benchmark, 2026], and the ability to eject to bare React Native if needed at scale.
Duolingo’s Half-Life Regression SRS is proprietary and requires massive data to train. Mellow uses FSRS (Free Spaced Repetition Scheduler), which achieves 99.6% superiority over SM-2 across 350M+ reviews in public benchmarks [open-spaced-repetition/srs-benchmark] and runs entirely on-device with no training data required.
2. System Architecture
+-------------------------------------------------------------+
| MOBILE (Expo) |
| |
| +----------+ +----------+ +-----------+ +-----------+ |
| | Expo | | Sensory | | Exercise | | SRS | |
| | Router | | Context | | Renderer | | (FSRS) | |
| +----+------+ +----+-----+ +-----+-----+ +-----+-----+ |
| | | | | |
| +----+--------------+--------------+---------------+-----+ |
| | API Client (fetch) | |
| +--------------------------+------------------------------+ |
| | |
| +--------------------------+------------------------------+ |
| | Local Storage (MMKV): preferences, SRS cards, cache | |
| +---------------------------------------------------------+ |
+-----------------------------+--------------------------------+
| HTTPS
v
+-------------------------------------------------------------+
| BACKEND (Fastify 5) |
| |
| +----------+ +----------+ +-----------+ +-----------+ |
| | Auth | | Lessons | | Feedback | | Payments | |
| | (Magic | | & SRS | | Pipeline | | (Stripe) | |
| | Link) | | Sync | | | | | |
| +----+------+ +----+-----+ +-----+-----+ +-----+-----+ |
| | | | | |
| +----+--------------+--------------+---------------+-----+ |
| | Drizzle ORM -> PostgreSQL | |
| +---------------------------------------------------------+ |
| |
| External APIs: |
| +-- Claude API (Haiku 4.5) -> exercise feedback |
| +-- Azure Speech -> pronunciation assessment |
| +-- Stripe API -> Pix + credit card payments |
+-------------------------------------------------------------+
2.1 Stack Decisions
| Layer | Technology | Rationale |
|---|---|---|
| Mobile | Expo SDK 55+ (React Native) | 83% of Expo projects use New Architecture; TurboModules + Fabric for near-native performance; file-based routing with Expo Router. 2,262+ production apps documented [Evan Bacon, 2026]. <5% performance gap vs bare RN [Meta Design Solutions]. |
| Navigation | Expo Router | File-based routing, typed routes, deep linking, web support for future landing page |
| State | React Context + MMKV | Sensory preferences in Context; SRS cards and cache in react-native-mmkv (synchronous, fast) |
| Backend | Fastify 5 + TypeBox | Fastest Node.js framework; schema validation with TypeBox; plugin architecture |
| ORM | Drizzle ORM | Type-safe SQL, lightweight, excellent PostgreSQL support, schema-first migrations |
| Database | PostgreSQL 18 | On Moklabs shared infra (devnest VPS or standalone Hostinger instance) |
| Auth | Magic link (email) | WCAG 2.2 3.3.8 Accessible Authentication — no CAPTCHA, no password cognitive load. React Native accessibility requires explicit props (accessibilityRole, accessibilityLabel) unlike web where HTML provides defaults [Accessibility Checker, 2025]. |
| AI Feedback | Claude Haiku 4.5 | Fast, cheap ($0.80/$4.00 per 1M tokens), follows structured output instructions precisely |
| Pronunciation | Azure Speech Pronunciation Assessment | Best phoneme-level scoring; $0.022/min; supports Portuguese + English |
| Payments | Stripe + Pix | Pix is 40%+ of Brazil online transactions; 1.5% fee vs 3.99% credit card |
| SRS | FSRS (ts-fsrs) | 99.6% superiority over SM-2, 20-30% fewer reviews for same retention, runs on-device [open-spaced-repetition benchmark, 350M reviews] |
2.2 Why Not These Alternatives
| Rejected | Reason |
|---|---|
| Native iOS + Android (Duolingo approach) | Requires 2x development effort. Justified at 50M DAU, not at 0-1K users. Duolingo has 200+ engineers; Mellow has 1-2. |
| Next.js / web-first | Target is mobile-first; autistic users prefer app predictability over browser |
| Supabase | Moklabs is migrating away from Supabase to standalone PostgreSQL |
| Prisma | Drizzle is lighter, faster cold starts, better for Fastify plugin model |
| Firebase Auth | Google dependency; magic link is simpler and WCAG-compliant |
| Duolingo-style gamification | Fundamentally incompatible with autism-friendly design. Streaks, hearts, and leaderboards create anxiety in autistic users. |
| Flutter | Would require learning Dart. Team expertise is TypeScript/React. Expo performance gap is <5%. |
3. Project Structure
3.1 Monorepo Layout
mellow/
+-- apps/
| +-- mobile/ # Expo app
| | +-- app/ # Expo Router file-based routes
| | | +-- _layout.tsx # Root layout (SensoryProvider wrap)
| | | +-- index.tsx # Home / dashboard
| | | +-- (auth)/
| | | | +-- login.tsx # Magic link input
| | | | +-- verify.tsx # Magic link verification
| | | +-- (onboarding)/
| | | | +-- sensory.tsx # Sensory preferences setup
| | | | +-- energy.tsx # Energy level intro
| | | +-- (tabs)/
| | | | +-- _layout.tsx # Tab navigator
| | | | +-- learn.tsx # Lesson selection
| | | | +-- review.tsx # SRS review deck
| | | | +-- progress.tsx # Progress dashboard
| | | | +-- settings.tsx # Sensory controls + account
| | | +-- lesson/
| | | | +-- [packId]/
| | | | | +-- index.tsx # Lesson list
| | | | | +-- [lessonId].tsx # Exercise runner
| | | +-- speak/
| | | +-- [exerciseId].tsx # Speaking practice
| | +-- components/
| | | +-- exercise/ # Exercise type renderers
| | | +-- feedback/ # AI feedback display
| | | +-- sensory/ # Sensory control components
| | | +-- ui/ # Base UI components (accessible)
| | +-- contexts/
| | | +-- SensoryContext.tsx # Sensory preferences provider
| | | +-- AuthContext.tsx # Auth state
| | | +-- EnergyContext.tsx # Current energy level
| | +-- lib/
| | | +-- api.ts # API client
| | | +-- fsrs.ts # FSRS algorithm (local)
| | | +-- storage.ts # MMKV wrapper
| | | +-- audio.ts # Audio recording/playback
| | +-- app.json
| | +-- package.json
| |
| +-- api/ # Fastify backend
| +-- src/
| | +-- server.ts # Fastify app entry
| | +-- plugins/
| | | +-- auth.ts # Magic link auth plugin
| | | +-- db.ts # Drizzle + PostgreSQL plugin
| | | +-- stripe.ts # Stripe/Pix plugin
| | +-- routes/
| | | +-- auth.ts # POST /auth/magic-link, /auth/verify
| | | +-- lessons.ts # GET /lessons, /lessons/:id
| | | +-- exercises.ts # POST /exercises/:id/submit
| | | +-- feedback.ts # POST /feedback (Claude API)
| | | +-- speech.ts # POST /speech/assess (Azure)
| | | +-- sync.ts # POST /sync (SRS state sync)
| | | +-- payments.ts # POST /payments/create-intent
| | +-- services/
| | | +-- claude.ts # Claude API client
| | | +-- azure-speech.ts # Azure Pronunciation Assessment
| | | +-- stripe.ts # Stripe + Pix service
| | +-- db/
| | | +-- schema.ts # Drizzle schema definitions
| | | +-- migrations/ # SQL migrations
| | | +-- seed.ts # Lesson content seed
| | +-- lib/
| | +-- email.ts # Magic link email sender
| | +-- prompts.ts # Claude system prompts
| +-- drizzle.config.ts
| +-- package.json
|
+-- packages/
| +-- shared/ # Shared types and constants
| +-- types.ts # Exercise, Lesson, Feedback types
| +-- constants.ts # Energy levels, categories
|
+-- package.json # Workspace root (npm workspaces)
+-- turbo.json # Turborepo config (optional)
3.2 Key Architectural Decisions
-
Local-first SRS: FSRS algorithm runs entirely on-device in MMKV. Server sync is optional (backup/restore). This means the app works offline for review sessions. FSRS requires 20-30% fewer reviews than SM-2 for the same retention level [open-spaced-repetition benchmark].
-
Backend-mediated AI: All Claude API and Azure Speech calls go through the Fastify backend. This protects API keys, enables caching, and allows cost monitoring per user.
-
Sensory preferences as React Context: Not in remote DB. These are device-local preferences that should be instant (no network latency on theme change).
-
Exercise state in local storage: In-progress exercise state persists in MMKV. User can close app mid-exercise and resume exactly where they left off.
4. Data Model (Drizzle Schema)
4.1 Core Tables
// db/schema.ts
import { pgTable, uuid, text, integer, timestamp,
boolean, jsonb, pgEnum, real } from 'drizzle-orm/pg-core';
// Enums
export const subscriptionTier = pgEnum('subscription_tier',
['free', 'plus', 'family']);
export const exerciseType = pgEnum('exercise_type',
['vocabulary', 'grammar', 'listening', 'speaking', 'translation']);
export const cefrLevel = pgEnum('cefr_level',
['a1', 'a2', 'b1', 'b2', 'c1', 'c2']);
// Users
export const users = pgTable('users', {
id: uuid('id').primaryKey().defaultRandom(),
email: text('email').notNull().unique(),
name: text('name'),
tier: subscriptionTier('tier').notNull().default('free'),
stripeCustomerId: text('stripe_customer_id'),
createdAt: timestamp('created_at').notNull().defaultNow(),
lastActiveAt: timestamp('last_active_at'),
});
// Magic Link Tokens
export const magicLinks = pgTable('magic_links', {
id: uuid('id').primaryKey().defaultRandom(),
email: text('email').notNull(),
token: text('token').notNull().unique(),
expiresAt: timestamp('expires_at').notNull(),
usedAt: timestamp('used_at'),
});
// Content Packs (Tech, Games, Daily Life)
export const contentPacks = pgTable('content_packs', {
id: uuid('id').primaryKey().defaultRandom(),
slug: text('slug').notNull().unique(),
name: text('name').notNull(),
namePt: text('name_pt').notNull(),
description: text('description').notNull(),
descriptionPt: text('description_pt').notNull(),
level: cefrLevel('level').notNull().default('a1'),
isFree: boolean('is_free').notNull().default(false),
sortOrder: integer('sort_order').notNull().default(0),
wordCount: integer('word_count').notNull().default(0),
});
// Lessons (10-15 per pack)
export const lessons = pgTable('lessons', {
id: uuid('id').primaryKey().defaultRandom(),
packId: uuid('pack_id').notNull().references(() => contentPacks.id),
slug: text('slug').notNull(),
title: text('title').notNull(),
titlePt: text('title_pt').notNull(),
sortOrder: integer('sort_order').notNull(),
grammarNote: text('grammar_note'),
grammarNotePt: text('grammar_note_pt'),
});
// Vocabulary Items
export const vocabulary = pgTable('vocabulary', {
id: uuid('id').primaryKey().defaultRandom(),
lessonId: uuid('lesson_id').notNull().references(() => lessons.id),
word: text('word').notNull(),
translation: text('translation').notNull(),
pronunciation: text('pronunciation'),
exampleSentence: text('example_sentence'),
exampleTranslation: text('example_translation'),
audioUrl: text('audio_url'),
imageUrl: text('image_url'),
sortOrder: integer('sort_order').notNull(),
});
// Exercises
export const exercises = pgTable('exercises', {
id: uuid('id').primaryKey().defaultRandom(),
lessonId: uuid('lesson_id').notNull().references(() => lessons.id),
type: exerciseType('type').notNull(),
sortOrder: integer('sort_order').notNull(),
content: jsonb('content').notNull(),
});
// User Progress (server-side backup of SRS state)
export const userProgress = pgTable('user_progress', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull().references(() => users.id),
vocabularyId: uuid('vocabulary_id').notNull().references(() => vocabulary.id),
stability: real('stability').notNull().default(0),
difficulty: real('difficulty').notNull().default(5),
retrievability: real('retrievability').notNull().default(1),
lastReview: timestamp('last_review'),
nextReview: timestamp('next_review'),
reps: integer('reps').notNull().default(0),
lapses: integer('lapses').notNull().default(0),
syncedAt: timestamp('synced_at').notNull().defaultNow(),
});
// Subscriptions
export const subscriptions = pgTable('subscriptions', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull().references(() => users.id),
stripeSubscriptionId: text('stripe_subscription_id'),
tier: subscriptionTier('tier').notNull(),
status: text('status').notNull(),
currentPeriodEnd: timestamp('current_period_end'),
paymentMethod: text('payment_method'),
createdAt: timestamp('created_at').notNull().defaultNow(),
});
// Session Logs (analytics, no PII)
export const sessionLogs = pgTable('session_logs', {
id: uuid('id').primaryKey().defaultRandom(),
userId: uuid('user_id').notNull().references(() => users.id),
energyLevel: text('energy_level').notNull(),
exercisesCompleted: integer('exercises_completed').notNull().default(0),
durationSeconds: integer('duration_seconds').notNull().default(0),
startedAt: timestamp('started_at').notNull().defaultNow(),
endedAt: timestamp('ended_at'),
});
4.2 Exercise Content Schema (JSONB)
// packages/shared/types.ts
interface VocabularyExercise {
type: 'vocabulary';
wordId: string;
prompt: 'image-to-word' | 'word-to-translation' | 'translation-to-word';
options: string[];
correctIndex: number;
}
interface GrammarExercise {
type: 'grammar';
sentence: string;
blank: string;
options: string[];
correctIndex: number;
explanation: string;
}
interface SpeakingExercise {
type: 'speaking';
targetPhrase: string;
referenceAudioUrl: string;
difficulty: 'word' | 'sentence' | 'paragraph';
}
interface TranslationExercise {
type: 'translation';
direction: 'pt-to-en' | 'en-to-pt';
sourceSentence: string;
acceptedTranslations: string[];
literalTranslation?: string;
}
5. API Design
5.1 Route Summary
| Method | Path | Auth | Tier | Description |
|---|---|---|---|---|
| POST | /auth/magic-link | No | — | Send magic link email |
| POST | /auth/verify | No | — | Verify token, return JWT |
| GET | /packs | Yes | — | List content packs (mark locked for free users) |
| GET | /packs/:packId/lessons | Yes | Varies | List lessons in pack |
| GET | /lessons/:lessonId | Yes | Varies | Get lesson with exercises |
| POST | /exercises/:id/submit | Yes | Varies | Submit answer, get AI feedback |
| POST | /speech/assess | Yes | Plus | Upload audio, get pronunciation score + feedback |
| POST | /sync | Yes | — | Sync SRS state (bidirectional merge) |
| POST | /payments/create-intent | Yes | — | Create Stripe PaymentIntent (Pix or card) |
| POST | /payments/webhook | No | — | Stripe webhook handler |
| GET | /me | Yes | — | User profile + subscription status |
| PATCH | /me | Yes | — | Update profile |
5.2 Auth Flow (Magic Link)
1. User enters email on login screen
2. POST /auth/magic-link { email }
3. Server generates token, stores in magic_links table (expires in 15 min)
4. Server sends email with deep link: mellow://verify?token=xxx
5. User taps link -> app opens -> POST /auth/verify { token }
6. Server validates token, creates/finds user, returns JWT
7. App stores JWT in MMKV secure storage
No password, no CAPTCHA, no OAuth complexity. WCAG 2.2 compliant. React Native requires explicit accessibilityRole="button" and accessibilityLabel on all interactive elements — unlike web HTML where semantic elements provide defaults [React Native Accessibility Docs].
5.3 Feedback Pipeline
User submits exercise answer
|
v
POST /exercises/:id/submit
{ exerciseId, answer, energyLevel }
|
+--- Check correctness locally (for simple vocab/grammar)
|
+--- If wrong OR if explanation needed:
| Call Claude Haiku 4.5 with:
| - System prompt (autism-specific, cached)
| - Exercise context (lesson, pack, grammar rule)
| - User's answer + correct answer
| -> Structured JSON feedback response
|
+--- Return to app:
{
correct: boolean,
feedback: string,
correction: { wrong, correct } | null,
explanation: string,
encouragement: string
}
5.4 Claude System Prompt (Cached)
You are a patient, clear English tutor for a Portuguese-speaking adult
learner at A1 level. Your student is autistic and prefers explicit,
concrete feedback.
RULES:
1. NEVER use sarcasm, irony, jokes, or figurative language
2. ALWAYS show the correct answer alongside the error
3. Explain WHY something is wrong in simple terms
4. Use Portuguese for grammar explanations when helpful
5. Keep sentences short (max 15 words per sentence)
6. One concept per response -- never bundle corrections
7. Use "You wrote X. The correct form is Y." format
8. Never say "try again" -- always provide the answer
9. Never create time pressure ("hurry", "quick", "before time runs out")
10. Acknowledge effort: "You got 4 out of 5 correct. Great practice."
OUTPUT FORMAT (JSON):
{
"feedback": "string -- main feedback message",
"correction": { "wrong": "string", "correct": "string" } | null,
"explanation": "string -- why (in Portuguese if grammar)",
"encouragement": "string -- effort-based, never comparative",
"nextHint": "string -- optional tip for next exercise"
}
This prompt (~500 tokens) is identical across all requests — use Anthropic prompt caching to reduce input cost by 90%.
6. Accessibility Architecture
6.1 SensoryContext Provider
The SensoryContext wraps the entire app and controls all sensory output. Preferences persist in MMKV and are set during onboarding.
interface SensoryPreferences {
// Visual
theme: 'light' | 'dark' | 'high-contrast';
fontSize: 'small' | 'medium' | 'large' | 'extra-large';
reducedMotion: boolean; // Also checks OS prefers-reduced-motion
dyslexiaFont: boolean; // Toggle Atkinson Hyperlegible
// Audio
soundEnabled: boolean;
soundVolume: number; // 0-100
musicEnabled: boolean;
pronunciationAutoPlay: boolean;
// Haptics
hapticsEnabled: boolean;
// Session
defaultEnergyLevel: 'high' | 'medium' | 'low' | 'browse';
breakReminders: boolean;
breakIntervalMinutes: number; // Default 15
}
6.2 Component Accessibility Requirements
Every component in the app MUST follow these rules:
| Rule | Implementation | Standard |
|---|---|---|
| Minimum 48px touch targets | minHeight: 48, minWidth: 48 on all pressable elements | WCAG 2.5.8 |
| Text labels on all icons | No icon-only buttons; always accessibilityLabel + visible text | WCAG 1.1.1 |
| No auto-play audio/video | User taps to play; pronunciationAutoPlay preference respected | WCAG 1.4.2 |
| Predictable layout | Same layout structure on every screen; no dynamic repositioning | WCAG 3.2.3 |
| No time pressure | Zero countdowns, timers, or urgency cues anywhere | WCAG 2.2.1 |
| Screen reader support | accessible, accessibilityLabel, accessibilityRole on all interactive elements | WCAG 4.1.2 |
| Color not sole indicator | Correct/incorrect shown with icon + text + color | WCAG 1.4.1 |
| Contrast ratio 7:1 | Enhanced contrast for text (AAA target) | WCAG 1.4.6 |
React Native accessibility note: Unlike web where <button> and <a> automatically expose semantics, React Native requires explicit accessibilityRole, accessibilityLabel, and accessibilityState props on every interactive element [React Native Docs, Accessibility Checker 2025 Guide].
6.3 Energy Check-In Flow
App launch (or session start)
|
v
+-------------------------------------+
| How are you feeling right now? |
| |
| [ Lots of energy (full session) ] |
| [ Some energy (quick review) ] |
| [ Low energy (just vocabulary) ] |
| [ Just browsing (no exercises) ] |
| |
| [Skip -- use last setting] |
+-------------------------------------+
|
v
Store in EnergyContext
-> Adapts FSRS deck size
-> Adapts session length
-> Adapts exercise difficulty
6.4 No-Guilt Messaging Framework
| Scenario | Message |
|---|---|
| Missed 3 days | ”Welcome back. You still know 127 words.” |
| Failed a card | ”The correct word is ‘keyboard’. Added to your review list.” |
| Low energy session | ”You reviewed 5 important words. That keeps them fresh.” |
| Quit mid-session | ”Your progress is saved. See you next time.” |
| Completed lesson | ”You completed Computer Parts. You learned 12 new words.” |
| 1 minute session | ”Great practice.” |
Counter-argument: Some research suggests that gamification (streaks, rewards) increases retention even for neurodivergent users. However, the specific pattern of punitive gamification (losing streaks, hearts as lives, competitive leaderboards) is what creates anxiety. Mellow’s approach uses positive reinforcement only (effort acknowledgment, cumulative word counts) without punishment for inactivity.
7. Payments Architecture
7.1 Pricing (BRL)
| Tier | Monthly | Annual | Includes |
|---|---|---|---|
| Free | R$ 0 | R$ 0 | 1 lesson/day, Daily Life pack, energy check-in |
| Plus | R$ 19.90 | R$ 149.90 | All packs, unlimited lessons, AI feedback, pronunciation, SRS |
| Family | R$ 29.90 | R$ 239.90 | Plus for up to 3 profiles |
Pricing rationale: Duolingo Super costs R$49.90/mo in Brazil. Babbel costs R$34.90/mo. Mellow’s R$19.90 is 60% below Duolingo and 43% below Babbel, reflecting (a) lower API costs due to local-first SRS, (b) niche targeting that requires accessible pricing, and (c) Pix payment efficiency (1.5% vs 3.99% card fees).
7.2 Stripe + Pix Flow
User taps "Upgrade to Plus"
|
v
POST /payments/create-intent
{ tier: 'plus', period: 'monthly', method: 'pix' }
|
v
Stripe creates PaymentIntent with Pix
|
v
App displays QR code (from Stripe response)
"Scan with your bank app. Expires in 30 minutes."
|
v
User scans QR in bank app -> payment confirmed
|
v
Stripe webhook -> POST /payments/webhook
event: payment_intent.succeeded
|
v
Server updates user.tier = 'plus'
Creates subscription record
|
v
App refreshes -> unlocks Plus features
7.3 Payment UX for Autistic Users
- Default to Pix (show QR code prominently)
- Clear timer: “This QR code expires in 30 minutes” (not “hurry!”)
- Explicit confirmation: “Payment received. Your Mellow Plus is now active.”
- Show exact amount in BRL before payment
- One-tap cancellation in settings — no “are you sure?” dark patterns
8. Cost Model
8.1 Per Active User Per Month
| Component | Usage Estimate | Cost |
|---|---|---|
| Claude Haiku 4.5 (with caching) | ~300 exercises | $0.16 |
| Azure Speech (pronunciation) | ~20 min speaking | $0.44 |
| Whisper (batch transcription) | ~10 min | $0.06 |
| Total API cost | $0.66/user/mo |
8.2 At Scale
| Active Users | Monthly API Cost | Revenue (100% Plus @ R$19.90) | Margin |
|---|---|---|---|
| 100 | $66 | ~$380 | 83% |
| 1,000 | $660 | ~$3,800 | 83% |
| 5,000 | $3,300 | ~$19,000 | 83% |
8.3 Optimization Levers
- Prompt caching: -50% on Claude cost
- On-device word pronunciation: -60% on Azure calls
- Response caching for identical vocab exercises: -30% on Claude calls
- Optimized cost: ~$0.35/user/mo
8.4 Comparison to Competitors’ Unit Economics
| App | Estimated API cost/user/mo | Subscription price | Gross margin |
|---|---|---|---|
| Duolingo | ~$0.10 (mostly on-device ML) | $7.99-13.99/mo | ~75% [public filings] |
| Babbel | ~$0.05 (minimal AI) | $6.95-13.95/mo | ~80% [estimated] |
| Mellow | $0.35-0.66 | R$19.90 (~$3.80/mo) | 83% |
Mellow’s higher per-user cost is offset by lower infrastructure overhead (no massive ML training, no custom recommendation engine).
9. Implementation Phases
Phase 1: MVP Core (Weeks 1-4)
| Task | Priority | Estimate |
|---|---|---|
| Scaffold Expo + Fastify monorepo | Critical | Week 1 |
| Drizzle schema + migrations | Critical | Week 1 |
| Magic link auth (Fastify + Expo) | High | Week 1 |
| SensoryContext + onboarding flow | High | Week 1-2 |
| Content pack + lesson data model | High | Week 2 |
| Seed A1 Daily Life pack (10 lessons, 100 words) | High | Week 2 |
| Exercise renderer (vocabulary, grammar, translation) | High | Week 2-3 |
| Energy check-in + adaptive session | High | Week 2 |
| FSRS engine (local, MMKV) | High | Week 3 |
| Claude feedback pipeline | High | Week 3 |
| Progress dashboard | Medium | Week 3-4 |
| Settings (sensory controls) | Medium | Week 4 |
MVP delivers: Login, onboarding, Daily Life pack, vocabulary/grammar/translation exercises with AI feedback, SRS review, energy check-in, full sensory controls.
Phase 2: Speaking + Payments (Weeks 5-8)
| Task | Priority | Estimate |
|---|---|---|
| Azure Speech pronunciation assessment | High | Week 5 |
| Speaking exercise UI (record, review, feedback) | High | Week 5-6 |
| Stripe + Pix integration | High | Week 6 |
| Subscription management | High | Week 6-7 |
| Tech + Games content packs | High | Week 7 |
| SRS cloud sync | Medium | Week 7 |
| Landing page (mellow.moklabs.io) | High | Week 8 |
| Beta deployment (TestFlight + Play Console) | High | Week 8 |
Phase 3: Launch (Weeks 9-12)
| Task | Priority | Estimate |
|---|---|---|
| Beta testing with 20-30 autistic adults | Critical | Week 9-10 |
| Iterate on feedback (accessibility fixes) | Critical | Week 10-11 |
| Ambassador program setup | High | Week 11 |
| Public launch (April 2026 — Autism Awareness Month) | High | Week 12 |
| App Store + Play Store submission | High | Week 12 |
10. Key Technical Risks
| Risk | Severity | Mitigation |
|---|---|---|
| Claude latency on exercise feedback | Medium | Pre-compute feedback for common exercises; cache responses; show optimistic UI. Haiku 4.5 p50 latency is <500ms. |
| Azure Speech API downtime | Low | Fallback to on-device iOS SpeechAnalyzer for basic scoring |
| Pix Automatico adoption for recurring | Medium | Support both one-time Pix and credit card recurring as fallback |
| Expo New Architecture breaking changes | Low | Pin SDK version; don’t use bleeding-edge native modules. 2,262+ apps in production demonstrate stability. |
| Content quality for A1 level | High | Co-design with autistic beta testers; hire Portuguese-English linguist. Budget R$5K for initial 3 packs. |
| FSRS implementation correctness | Low | Use reference implementation from open-spaced-repetition/ts-fsrs. Proven across 350M+ reviews. |
| Accessibility testing coverage | Medium | Use Expo accessibility testing tools + manual testing with screen readers (VoiceOver, TalkBack). Recruit autistic testers for beta. |
11. Existing Autism EdTech Landscape
While no app combines autism accessibility with language learning, several apps serve adjacent markets:
| App | Focus | Users | Funding | Limitation for Mellow’s use case |
|---|---|---|---|---|
| Otsimo | Special education games for children with ASD | 150K+ globally | ~$300K (angel) | Children-focused, not language learning for adults |
| Floreo | VR social skills for ASD | N/A | Undisclosed | VR-based, not mobile language learning |
| Cognoa | ML-based autism screening | N/A | $100M+ | Diagnostic, not educational |
| NAVIS (Vanderbilt) | VR interview simulator for neurodivergent adults | Research phase | $70K grant [2026] | Interview skills, not language learning |
The Autism Tech Accelerator (2026) offers a 10-week program for autism-focused startups — Mellow could apply for mentorship and investor exposure (no equity, no fees) [Opportunities for Youth].
12. Mapping to Paperclip Issues
| Paperclip Issue | Blueprint Section |
|---|---|
| Scaffold Mellow project: React Native + Fastify + PostgreSQL | S2 Project Structure, S2.1 Stack |
| Design and implement lesson schema | S4 Data Model |
| Implement magic link auth and autism-friendly onboarding | S5.2 Auth Flow, S6.3 Energy Check-In |
| Create A1 content: 3 special interest packs | S4.2 Exercise Content, S9 Phase 1-2 |
| Implement sensory controls: sounds, animations, colors, font size | S6.1 SensoryContext, S6.2 Component Rules |
| Build explicit feedback system with Claude API integration | S5.3 Feedback Pipeline, S5.4 System Prompt |
| Implement energy check-in and session preview flow | S6.3 Energy Check-In, S6.4 Messaging |
| Integrate Stripe payments with Pix | S7 Payments Architecture |
| Implement async speaking: record, get AI pronunciation feedback | S5.1 Speech Route, Azure Speech integration |
| Build Mellow landing page (mellow.moklabs.io) | S9 Phase 2 |
Sources
- Duolingo Q3 2025 Shareholder Letter — 50M DAU, 185M MAU, 41% revenue growth
- Duolingo Q1 2025 — $230.7M revenue, 10.3M paid subscribers
- Duolingo Engineering Blog — Architecture & App Startup
- Does Duolingo Use React Native — Tech Stack Analysis
- Babbel Revenue & Usage Statistics 2026 — $352M revenue 2024
- Busuu Revenue & Usage Statistics 2026 — $45M revenue 2024
- Language Learning App Market Size — $7.36B in 2025, 16.15% CAGR
- Language Learning Revenue and Usage Statistics 2026
- Expo 2026: The Best Way to Build Cross-Platform Apps — <5% performance gap
- Who’s Using Expo in 2026 — 2,262+ production apps
- Best 40+ Expo App Examples Across Industries 2026
- FSRS Algorithm — 99.6% superiority over SM-2, 350M+ reviews benchmarked
- FSRS vs SM-2: Complete Guide — 20-30% fewer reviews
- SRS Benchmark — open-spaced-repetition
- IBGE Census 2022 — 2.4 million diagnosed ASD in Brazil
- Tismoo/CDC — Brazil could have 6.9 million autistic individuals
- Neurodiversity Statistics — 15-20% of global population
- Autism Tech Accelerator 2026 — 10-week startup program
- Otsimo — Special Education App for Autism
- Neurodiverse Technologies NAVIS — $70K Vanderbilt grant
- React Native Accessibility Best Practices 2025
- React Native Accessibility Docs
- Expo Router Introduction
- Fastify 5 + Drizzle Starter Kit
- Azure Speech Pronunciation Assessment Pricing
- Stripe Pix Payments Guide for Brazil
- Anthropic Claude API Documentation
- Prior Mellow Research: Neurodivergent EdTech Accessibility Patterns (2026-03-20)
- Prior Mellow Research: Brazil EdTech GTM 2026 (2026-03-20)
- Prior Mellow Research: AI-Powered Explicit Feedback Design (2026-03-20)