0af8e648fed0a951e64fb824c77b1571a3e42761
Crash: Swift/NativeDictionary.swift:792 Fatal error: Duplicate values for key: 'imp_tú', triggered the first time a user rated a vocab card and the in-flight example generation tried to materialise. Root cause: VerbExampleGenerator.generate() builds a [tenseId: example] dictionary from the model's output via Dictionary(uniqueKeysWithValues:), which traps on duplicates. The generator's @Generable schema declares @Guide(.count(6)) on the examples array, so the LLM is forced to return exactly 6. The new Vocab Flashcards / Multiple Choice views called generate(... tenseIds: ["ind_presente"]) — only one tense — which left the model to invent the other 5 tenseIds; it duplicated 'imp_tú' and the dictionary init trapped. Three fixes: Services/VerbExampleGenerator.swift — use Dictionary(_:uniquingKeysWith:) with first-wins so the generator can never crash regardless of caller shape. Views/Practice/Vocab/VocabFlashcardPracticeView.swift and Views/Practice/Vocab/VocabMultipleChoicePracticeView.swift — pass the canonical 6-tense set (VocabExampleTenseIds.canonical, same as VerbDetailView uses), then pick the ind_presente example for the card. Caches all six in VerbExampleCache as a side effect. Views/Verbs/VerbListView.swift — replace empty-string systemImage on the Level menu Labels with "circle" so the device console isn't spammed with "No symbol named '' found in system symbol set" every time the user opens the filter menu. The crash analysis I gave earlier (CloudKit schema migration of VerbReviewCard) was wrong — device console shows the real culprit. No CloudKit-side changes needed; the new model stays in the cloud container. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Conjuga
A Spanish-learning iOS app that combines verb conjugation practice, a full textbook reader, an AI conversation partner, offline dictionary lookups, grammar exercises, and more. Runs entirely on-device where possible (Foundation Models, Speech framework, Vision OCR).
Features
Verb practice
- Six conjugation modes — flashcards, typing, multiple choice, handwriting (Apple Pencil / finger), sentence builder, and full-table (conjugate all persons at once)
- Focus modes — weak verbs (SM-2 spaced repetition), irregularity drills (spelling / stem / unique), common tenses
- 1,750 verbs across 5 levels (Basic → Expert) with 209 K pre-conjugated forms and 23 K irregular-span annotations
- 20 tenses — every indicative, subjunctive, conditional, and imperative tense, each with character-level irregular highlighting
- Verb list filters — search by level, by irregularity (Any / Spelling Change / Stem Change / Unique Irregular), or by reflexive only (curated 100-verb list); filters compose
- Practice pool filters (Settings) — multi-select per level, per tense, per irregular-type, plus a "reflexive verbs only" toggle. Practice pool = intersection of all four.
- Verb detail pages — conjugation table, six AI-generated example sentences (one per core tense), and reflexive infinitive + preposition hint for curated reflexive verbs
- Text-to-speech on any form
Content & study
- Textbook reader — 30 chapters of Complete Spanish Step-by-Step with 251 interactive exercises (keyboard + Apple Pencil), 931 OCR'd vocab tables rendered as Spanish→English grids (~3 100 paired cards extracted via bounding-box OCR)
- Course decks — weekly vocab decks with example sentences, week tests, and cumulative checkpoint exams
- Stem-change toggle on Week 4 flashcard decks (E-IE, E-I, O-UE, U-UE) showing inline present-tense conjugations
- Grammar guide — 20 tense guides with usage rules and examples + 36 grammar topic notes (ser/estar, por/para, preterite/imperfect, reflexives, subjunctive triggers, etc.), each with 100+ practice exercises
- Grammar exercises — interactive quizzes for 5 core topics (ser/estar, por/para, preterite/imperfect, subjunctive, personal a)
- Curated YouTube videos — 54 hand-picked videos attached to guide and grammar items (preference for The Language Tutor's numbered lessons + BaseLang). Each item offers three actions: Stream (opens YouTube app / Safari), Download (YouTubeKit extraction + AVFoundation mux for modern adaptive-stream videos), Play (full-screen AVPlayer from local MP4). Settings → Downloaded Videos lists all downloads with total size, per-item delete, and a 500 MB warning.
AI & speech
- Conversational practice — on-device AI chat partner (Apple Foundation Models) with 10 scenario types; chat bubbles have tappable words that open dictionary / on-demand AI lookup
- AI short stories — generated stories with tappable words and comprehension quizzes
- Listening practice — listen-and-type + pronunciation scoring via the Speech framework
- Pronunciation check — word-by-word match scoring
Vocabulary & tools
- Offline dictionary — reverse index of 175 K verb forms + 200 common words, cached to disk for instant lookups
- Vocab SRS review — spaced repetition over course vocabulary with Again / Hard / Good / Easy rating
- Cloze practice — fill-in-the-blank sentences with distractor generation
- Lyrics practice — search, translate, and read Spanish song lyrics; long-press any word for an instant definition + tense/person readout (for verbs)
Tracking & sync
- Progress — streaks, daily goals, accuracy stats, achievement badges, study-time tracking per day
- CloudKit sync — review progress, test results, saved stories, conversations, and textbook attempts sync across devices
- Widgets — combined dashboard + word-of-the-day, refreshed daily and on backgrounding
Architecture
- SwiftUI + SwiftData with a dual-store configuration:
- Local store (App Group
group.com.conjuga.app) — reference data + per-device artifacts: verbs, forms, irregular spans, tense guides, course decks, vocab cards, textbook chapters, and downloaded videos. Seeded from bundled JSON on first launch. Self-healing re-seeds trigger on version bumps or if rows are missing on disk. - Cloud store (CloudKit
iCloud.com.conjuga.app, private database) — user data: review cards, course reviews, user progress, test results, daily logs, saved songs, stories, conversations, textbook exercise attempts.
- Local store (App Group
- SharedModels Swift Package shared between the app and widget extension. Widget schema must include every local-store entity or SwiftData destructively migrates the shared store.
- Foundation Models for on-device AI generation (
@Generablestructs for typed output) — conversation partner, short stories, verb-detail example sentences. - Vision framework for OCR of textbook pages and vocabulary images.
- Speech framework for recognition and pronunciation scoring.
- YouTubeKit (SPM) for video stream URL extraction, paired with AVFoundation (
AVMutableComposition+AVAssetExportSessionpassthrough) to mux separate DASH video + audio tracks into a single MP4 when progressive streams aren't available. - Textbook extraction pipeline (
Conjuga/Scripts/textbook/) — XHTML and answer-key parsers, macOS Vision image OCR + PDF page OCR, bounding-box vocab pair extractor, NSSpellChecker-based validator, and language-aware auto-fixer. - Video curation tooling (
Conjuga/Scripts/generate_videos_markdown.py) — regeneratesConjuga/youtube_videos.mdwith per-video channel, upload date, duration, view count, and like count (pulled via yt-dlp).
Requirements
- iOS 26+ (Foundation Models, Liquid Glass, modern Swift concurrency)
- Xcode 26+
- Apple Intelligence-capable device for AI features (conversation partner, AI stories, verb-detail examples); other features degrade gracefully
Building
Open Conjuga/Conjuga.xcodeproj in Xcode and run on a simulator or device. Reference data seeds automatically on first launch. To regenerate textbook content, run Conjuga/Scripts/textbook/run_pipeline.sh locally — the generated textbook_data.json / textbook_vocab.json are committed so fresh clones build without the pipeline.
Description
Languages
Swift
86.1%
Python
11.9%
HTML
1.7%
Shell
0.3%