This document provides a high-level introduction to KanaDojo, a web-based Japanese language learning platform. It covers the application's purpose, architecture, technology stack, and how major systems interconnect. For detailed information about specific subsystems, see the Architecture section (#2) and subsequent chapters.
KanaDojo is a Next.js 15 web application for learning Japanese language fundamentals. The codebase is organized around three learning domains ("dojos"):
| Dojo | Content | File Location | Route |
|---|---|---|---|
| Kana | Hiragana/Katakana syllabaries | features/Kana/data/kana.ts | /[locale]/kana |
| Kanji | JLPT N5-N2 characters | public/data-kanji/*.json | /[locale]/kanji |
| Vocabulary | JLPT N5-N2 word sets | public/data-vocab/*.json | /[locale]/vocabulary |
The architecture uses:
features/ (Kana, Kanji, Vocabulary, Preferences, Progress, Achievements, etc.)useKanaStore, useKanjiStore, useVocabStore, useStatsStore, usePreferencesStore) with localStorage persistence via zustand/middlewarefeatures/Preferences/data/themes.ts and features/Preferences/lib/theme/buildTheme.tsmiddleware.tsSources: README.md37-55 next.config.ts1-164 middleware.ts1-39
The following diagram maps natural language concepts to concrete code entities:
Figure 1: KanaDojo System Architecture with Code References
Key architectural patterns:
app/layout.tsx is server-rendered (metadata, analytics), app/ClientLayout.tsx is client-rendered (theme application, user interactions)shared/lib/adaptiveSelection.ts provides a singleton GlobalAdaptiveSelector using IndexedDB for weight persistencefeatures/Preferences/lib/theme/ transform base themes into full color palettes without component coupling[locale], [type], [mode] for internationalized training routesSources: app/layout.tsx1-207 app/ClientLayout.tsx1-151 middleware.ts1-39
| Category | Technologies | Purpose |
|---|---|---|
| Core Framework | Next.js 15, React 19, TypeScript 5 | Server-side rendering, type safety, app routing |
| Styling | Tailwind CSS, shadcn/ui, Framer Motion | Utility-first CSS, component library, animations |
| State Management | Zustand, Zustand Persist | Lightweight state with localStorage persistence |
| Data Storage | localStorage, IndexedDB | User preferences, adaptive learning weights |
| Internationalization | next-intl | Multi-language support with 9 namespaces |
| Audio | use-sound | Sound effect feedback system |
| Build Tools | ESLint, next-sitemap | Code quality, SEO optimization |
| Analytics | @vercel/analytics, @vercel/speed-insights | Usage tracking, performance monitoring |
Sources: README.md152-193 package.json
The codebase follows a feature-based organization with strict layer separation:
Figure 2: Directory Organization with Import Flow
Layer Import Rules (enforced by ESLint in eslint.config.mjs):
app/ → can import from features/, shared/, core/features/ → can import from shared/, other features/ (via public exports)shared/ → cannot import from features/ (prevents circular dependencies)core/ → minimal dependencies (infrastructure only)Feature Module Structure (example: features/Kanji/):
features/Kanji/
├── components/ # UI components (KanjiCards, LevelSetCards)
├── services/ # Data fetching (kanjiDataService.ts)
├── store/ # Zustand store (useKanjiStore.ts)
├── types/ # TypeScript interfaces
└── index.ts # Public facade (exports only what other features need)
Key Design Decisions:
features/Kana/data/kana.ts (small, can be bundled), Kanji/Vocab data is in public/ (large JSON files, fetched on demand)'kana-storage', 'kanji-storage', etc.)shared/components/ui/ are generated and customized locallyfeatures/Preferences/data/themes.ts → buildTheme() generates full themes → applyTheme() sets CSS variablesSources: README.md347-403 next.config.ts34-42 ESLint configuration inferred from diagrams
Learning content is structured for efficient loading and modularity:
| Content Type | File Location | Organization | Loading Strategy |
|---|---|---|---|
| Kana | features/Kana/data/kana.ts | KanaGroup[] grouped by type (Hiragana/Katakana) and category (Base, Dakuon, Yoon, Foreign) | Bundled (5KB, static import) |
| Kanji | public/data-kanji/N5.jsonpublic/data-kanji/N4.jsonpublic/data-kanji/N3.jsonpublic/data-kanji/N2.jsonpublic/data-kanji/decorations.json | JLPT levels, each JSON contains Kanji[] with character, readings, meanings | Lazy loaded via fetch() in features/Kanji/services/kanjiDataService.ts |
| Vocabulary | public/data-vocab/n5.jsonpublic/data-vocab/n4.jsonpublic/data-vocab/n3.jsonpublic/data-vocab/n2.json | JLPT levels, each JSON contains VocabWord[] with word, readings, meanings, wordTypes | Lazy loaded via fetch() in features/Vocabulary/services/vocabDataService.ts |
| Facts | public/japan-facts.json | string[] of Japan/Japanese language facts | Lazy loaded in shared/components/misc/RandomFact.tsx with module-level cache |
| Proverbs | public/japanese-proverbs.json | Proverb[] with Japanese text and English translation | Lazy loaded on demand |
Data Service Pattern (Kanji example):
This pattern ensures:
Caching Strategy:
factsCache variable with loading promise deduplication in RandomFact.tsx:7-23GlobalAdaptiveSelector in shared/lib/adaptiveSelection.tsFor detailed content data structures, see Data Organization (#2.4).
Sources: shared/components/misc/RandomFact.tsx1-64 app/layout.tsx189-192
Figure 3: State Management Data Flow
State flows through Zustand stores which automatically persist to localStorage via the Zustand Persist middleware. Each feature has its own store (useKanaStore, useKanjiStore, useVocabStore) for managing content selections and game modes. The useStatsStore tracks progress across all content types. The usePreferencesStore manages UI customization settings.
For detailed state management architecture, see State Management (#2.3).
Sources: README.md457-464
The training flow involves component orchestration, routing, and state updates:
Figure 4: Training Session Flow with Code References
Key Components:
Content Selection:
DojoMenu component renders dojo-specific cardsKanjiCards → LevelSetCards (N5, N4, N3, N2)useKanjiStore() with localStorage key 'kanji-storage'Selection Display:
SelectionStatusBar uses getSelectionLabels() utility to format ranges[1, 2, 3, 5, 7, 8, 9] → "1-3, 5, 7-9"Game Mode Selection:
GameModes modal persists mode choice to store'pick', 'input', 'pick-reverse', 'input-reverse', 'word-building'Routing:
app/[locale]/[type]/train/[mode]/page.tsx/en/kanji/train/pick → renders PickGame with Kanji dataAdaptive Question Generation:
GlobalAdaptiveSelector singleton in shared/lib/adaptiveSelection.ts'adaptive-weights' to persist character weightsStatistics Tracking:
useStatsStore() tracks per-session and cumulative statssaveSession() function updates:
characterMastery object)For detailed game mode implementations, see Game System (#4).
Sources: High-level diagram 3, shared/components/misc/RandomFact.tsx1-64 (similar caching pattern)
The theme system uses mathematical color generation from minimal input:
Figure 5: Theme Generation and Application Pipeline
Theme Generation Mathematics (OKLCH color space):
| Generated Color | Light Mode Formula | Dark Mode Formula | Purpose |
|---|---|---|---|
cardColor | l + 0.05, c * 0.5 | l + 0.1, c * 1.2 | Elevated surfaces |
borderColor | l - 0.1, c * 0.3 | l + 0.15, c * 0.8 | Subtle dividers |
mainAccentColor | l - 0.1, c * 1.2 | l - 0.1, c * 1.2 | Interactive states (hover) |
secondaryAccentColor | l - 0.1, c * 1.2 | l - 0.1, c * 1.2 | Secondary interactions |
Key Functions:
buildTheme(baseTheme: BaseTheme, isLight: boolean): Theme:
parseOklch()Theme objectapplyTheme(themeId: string): void:
THEME_GROUPS array by IDbuildTheme() with isLight flag from BaseThemeGroupdocument.documentElementdata-theme attribute for potential CSS selectorsuseCrazyMode() (in features/CrazyMode/):
usePathname() hookTHEME_GROUPSapplyTheme()CSS Variable Integration:
className="bg-[var(--card-color)] text-[var(--main-color)]"Persistence:
usePreferencesStore() with localStorage key 'preferences-storage'applyTheme() called in ClientLayout on mount: useEffect(() => { applyTheme(effectiveTheme); }, [effectiveTheme]);For 100+ theme definitions and generation details, see Theming System (#3.2).
Sources: app/ClientLayout.tsx83-90 High-level diagram 4
A typical user session involves this sequence of components and state changes:
Figure 6: Complete User Journey with State Flow
Key Interactions:
Initial Load (app/layout.tsx:132-207):
ClientLayout mounts, reads usePreferencesStore() from localStorageapplyTheme() before first paintNavigation (app/ClientLayout.tsx:1-151):
Sidebar component provides navigation linksnext-scroll-restorationContent Selection:
SelectionStatusBar displays formatted selection summaryTraining Configuration:
TrainingActionBar checks if selections existGameModes modal shows available modes (Pick, Input, Word Building)Game Session:
GlobalAdaptiveSelector generates questions based on performance historyuseStatsStore() in real-timeCompletion and Review:
Return component shows session summary with star ratinguseAchievementStore() checks unlock conditionsuseStatsStore() for visualizationSources: app/layout.tsx132-207 app/ClientLayout.tsx56-150 High-level diagrams 3, 6
Each feature follows this structure:
features/[FeatureName]/
├── components/ # Feature-specific UI components
├── store/ # Zustand store for feature state
├── data/ or services/ # Static data or data fetching services
├── lib/ # Feature-specific utilities
├── types/ # TypeScript types
└── index.ts # Barrel export for public API
Features export their public API through index.ts and can import from shared/ or other features when needed. The facade pattern is used in features like Preferences (useThemePreferences, useAudioPreferences) and Progress (useGameStats, useStatsDisplay) to provide controlled access to internal stores.
Sources: README.md449-456 README.md196-208
Routes follow the pattern: /[locale]/[feature]/[action]/[param]
Examples:
/en/kana - Kana dojo main page/en/kanji/train/pick - Kanji pick game/en/vocabulary/train/word-building - Vocabulary word building game/en/preferences - Settings page/en/progress - Statistics pageThe [locale] segment enables internationalization. For routing details, see Routing and Internationalization (#2.6).
Sources: README.md379-392 README.md477-485
KanaDojo is a sophisticated Japanese learning platform built on modern web technologies with a focus on architecture quality, user experience, and maintainability. The feature-based organization, comprehensive state management, and flexible theming system provide a solid foundation for continuous enhancement. The following chapters explore each system in detail, explaining implementation specifics, design decisions, and extension points.
Sources: README.md1-655 High-level diagrams provided
Refresh this wiki
This wiki was recently refreshed. Please wait 5 days to refresh again.