# japanese-learning > Japanese language learning app combining video lessons, interactive games, flashcards with spaced repetition, text-to-speech pronunciation, vocabulary (400+ words), verbs (35+), kanji (50+), and progress tracking. - Author: sanctum - Repository: kinggkoopa/sanctum-network - Version: 20260202215920 - Stars: 1 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/kinggkoopa/sanctum-network - Web: https://mule.run/skillshub/@@kinggkoopa/sanctum-network~japanese-learning:20260202215920 --- --- name: japanese-learning description: Japanese language learning app combining video lessons, interactive games, flashcards with spaced repetition, text-to-speech pronunciation, vocabulary (400+ words), verbs (35+), kanji (50+), and progress tracking. version: 2.0 --- # Japanese Learning App Skill ## Overview Comprehensive Japanese learning platform combining: - Video lessons (streaming app integration) - Interactive learning games (8+ game types) - Flashcard system with spaced repetition - Text-to-speech pronunciation with Japanese voice - Progress tracking with statistics - 400+ vocabulary words, 35+ verbs, 50+ kanji ## File Structure ``` japanese/ ├── index.html # Splash page with mode selection ├── player.html # Video learning mode ├── learn.html # Interactive games and study ├── data.json # Video playlists and app config ``` ## Design Aesthetic ```css :root { --bg: #0c0a09; --surface: #1a1614; --surface-2: #242020; --surface-3: #2e2a2a; --text: #f5f0eb; --text-2: #a8a098; --text-3: #685850; --red: #dc2626; /* Japanese red */ --red-soft: rgba(220, 38, 38, 0.15); --gold: #d4af37; --blue: #3b82f6; /* Audio/interactive */ --green: #22c55e; /* Success */ --font-display: 'Noto Serif JP', serif; --font-body: 'Inter', sans-serif; --font-japanese: 'Noto Sans JP', sans-serif; } ``` ## Data Structures ### Vocabulary Data (400+ words) ```javascript const VOCABULARY = { greetings: [ { japanese: 'おはようございます', reading: 'ohayou gozaimasu', english: 'Good morning (polite)', level: 'N5' }, { japanese: 'こんにちは', reading: 'konnichiwa', english: 'Hello/Good afternoon', level: 'N5' }, { japanese: 'こんばんは', reading: 'konbanwa', english: 'Good evening', level: 'N5' }, { japanese: 'おやすみなさい', reading: 'oyasuminasai', english: 'Good night', level: 'N5' }, { japanese: 'さようなら', reading: 'sayounara', english: 'Goodbye', level: 'N5' }, { japanese: 'ありがとうございます', reading: 'arigatou gozaimasu', english: 'Thank you (polite)', level: 'N5' }, { japanese: 'すみません', reading: 'sumimasen', english: 'Excuse me / Sorry', level: 'N5' }, { japanese: 'いただきます', reading: 'itadakimasu', english: 'Expression before eating', level: 'N5' }, { japanese: 'ごちそうさまでした', reading: 'gochisousama deshita', english: 'Expression after eating', level: 'N5' } ], food: [ { japanese: 'ごはん', reading: 'gohan', english: 'Rice / Meal', level: 'N5' }, { japanese: 'パン', reading: 'pan', english: 'Bread', level: 'N5' }, { japanese: '水', reading: 'mizu', english: 'Water', level: 'N5' }, { japanese: 'お茶', reading: 'ocha', english: 'Tea', level: 'N5' }, { japanese: 'コーヒー', reading: 'koohii', english: 'Coffee', level: 'N5' }, { japanese: '肉', reading: 'niku', english: 'Meat', level: 'N5' }, { japanese: '魚', reading: 'sakana', english: 'Fish', level: 'N5' }, { japanese: '野菜', reading: 'yasai', english: 'Vegetables', level: 'N5' } ], // ... more categories: family, numbers, time, places, adjectives, etc. }; ``` ### Verb Data (35+ verbs with conjugations) ```javascript const VERBS = { godan: [ { dictionary: '食べる', reading: 'taberu', english: 'to eat', type: 'ichidan', conjugations: { masu: '食べます', te: '食べて', ta: '食べた', nai: '食べない', potential: '食べられる', passive: '食べられる', causative: '食べさせる', imperative: '食べろ', volitional: '食べよう' } }, { dictionary: '行く', reading: 'iku', english: 'to go', type: 'godan', conjugations: { masu: '行きます', te: '行って', ta: '行った', nai: '行かない', potential: '行ける', passive: '行かれる', causative: '行かせる' } } // ... more verbs ] }; ``` ### Kanji Data (50+ kanji) ```javascript const KANJI = { n5: [ { kanji: '日', meanings: ['day', 'sun', 'Japan'], onyomi: ['ニチ', 'ジツ'], kunyomi: ['ひ', 'か'], examples: [ { word: '日本', reading: 'にほん', meaning: 'Japan' }, { word: '今日', reading: 'きょう', meaning: 'today' }, { word: '日曜日', reading: 'にちようび', meaning: 'Sunday' } ], strokes: 4, radical: '日' }, { kanji: '月', meanings: ['month', 'moon'], onyomi: ['ゲツ', 'ガツ'], kunyomi: ['つき'], examples: [ { word: '月曜日', reading: 'げつようび', meaning: 'Monday' }, { word: '一月', reading: 'いちがつ', meaning: 'January' } ], strokes: 4, radical: '月' } // ... more kanji ] }; ``` ### Hiragana & Katakana ```javascript const HIRAGANA = { basic: [ { char: 'あ', romaji: 'a', row: 'vowel' }, { char: 'い', romaji: 'i', row: 'vowel' }, { char: 'う', romaji: 'u', row: 'vowel' }, { char: 'え', romaji: 'e', row: 'vowel' }, { char: 'お', romaji: 'o', row: 'vowel' }, { char: 'か', romaji: 'ka', row: 'k' }, { char: 'き', romaji: 'ki', row: 'k' }, // ... complete 46 basic hiragana ], dakuten: [ { char: 'が', romaji: 'ga', row: 'g' }, { char: 'ぎ', romaji: 'gi', row: 'g' }, // ... voiced consonants ], combo: [ { char: 'きゃ', romaji: 'kya' }, { char: 'きゅ', romaji: 'kyu' }, { char: 'きょ', romaji: 'kyo' }, // ... combination characters ] }; const KATAKANA = { // Same structure as hiragana basic: [ { char: 'ア', romaji: 'a', row: 'vowel' }, // ... ] }; ``` ## Text-to-Speech Implementation ### CRITICAL: Browser Speech Synthesis ```javascript let japaneseVoice = null; let speechReady = false; function initVoices() { const voices = speechSynthesis.getVoices(); // Priority order for Japanese voices japaneseVoice = voices.find(v => v.lang === 'ja-JP' && v.name.includes('Google')) || voices.find(v => v.lang === 'ja-JP') || voices.find(v => v.lang.startsWith('ja')) || voices.find(v => v.name.toLowerCase().includes('japanese')); speechReady = true; console.log('Japanese voice:', japaneseVoice?.name || 'Using default'); } // Voices load asynchronously - MUST handle this if (speechSynthesis.getVoices().length > 0) { initVoices(); } speechSynthesis.onvoiceschanged = initVoices; function speak(text, rate = 0.8) { if (!speechReady) { console.warn('Speech not ready yet'); return; } // Cancel any current speech speechSynthesis.cancel(); const utterance = new SpeechSynthesisUtterance(text); utterance.lang = 'ja-JP'; utterance.rate = rate; utterance.volume = 1.0; if (japaneseVoice) { utterance.voice = japaneseVoice; } // Visual feedback utterance.onstart = () => { document.querySelectorAll('.audio-btn.active').forEach(b => b.classList.remove('active')); event?.target?.classList?.add('active'); }; utterance.onend = () => { event?.target?.classList?.remove('active'); }; utterance.onerror = (e) => console.error('Speech error:', e); speechSynthesis.speak(utterance); } ``` ### Audio Button with Tactile Feedback ```html ``` ```css .audio-btn { width: 48px; height: 48px; background: linear-gradient(145deg, var(--blue), #2563eb); border: none; border-radius: 50%; color: white; font-size: 1.2rem; cursor: pointer; transition: all 0.15s cubic-bezier(0.34, 1.56, 0.64, 1); box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3); } .audio-btn:hover { transform: scale(1.1) translateY(-2px); box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4); } .audio-btn:active { transform: scale(0.95); background: var(--green); } .audio-btn.active { animation: pulse 0.5s ease-in-out infinite; background: var(--green); } @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.1); } } ``` ## Game Types ### 1. Flashcard Mode ```javascript function FlashcardGame(category) { let cards = shuffle([...VOCABULARY[category]]); let currentIndex = 0; let showAnswer = false; function render() { const card = cards[currentIndex]; return `