A personalized, interactive English learning web app designed for Eli, a 10-year-old beginner in Zagreb. Features themed lessons (K-pop, Harry Potter, skiing), multiple game types, progress tracking, and a tutor dashboard—all running fully in the browser with no external APIs.
- Personalized Experience: Greets Eli by name, tracks her progress, and awards personalized badges
- Multiple Game Types:
- 📇 Flashcards with images and audio
- ✅ Multiple choice quizzes
- 💬 Branching dialogue conversations
- 🎮 More games (drag-and-drop, memory, puzzles) can be added easily
- Three Themes: K-pop, Harry Potter, and Skiing with custom color schemes
- Progress Tracking: Streaks, points, badges, and detailed analytics
- Tutor Dashboard: PIN-protected dashboard with usage statistics and progress export
- Fully Offline: All data stored in browser localStorage, no external APIs
- Responsive Design: Works on tablets, laptops, and desktops
- Node.js (version 16 or higher)
- npm (comes with Node.js)
-
Clone or download this repository
-
Install dependencies:
npm install
-
Run the development server:
npm run dev
-
Open your browser to
http://localhost:5173
npm run buildThis creates a dist/ folder with all static files ready for deployment.
npm run previewElisEnglish/
├── lessons/ # Lesson JSON files
│ ├── kpop-greetings.json
│ ├── skiing-basics.json
│ └── hogwarts-house.json
├── voice-lessons/ # Voice lesson modules (future)
├── assets/
│ ├── audio/ # Audio files for vocabulary
│ └── images/ # Images for vocabulary and themes
├── src/
│ ├── components/ # React components
│ │ ├── Games/ # Game components (Flashcard, MultipleChoice, etc.)
│ │ ├── Home/ # Home screen
│ │ ├── Lessons/ # Lesson browser and player
│ │ ├── Badges/ # Badge gallery
│ │ ├── Settings/ # Settings page
│ │ ├── Tutor/ # Tutor dashboard
│ │ └── Layout/ # Navigation and layout
│ ├── contexts/ # React contexts (Theme, Progress)
│ ├── hooks/ # Custom hooks (speech synthesis)
│ ├── services/ # Core services (storage, lesson loader, progress tracker)
│ ├── types/ # TypeScript type definitions
│ ├── styles/ # Global styles and design tokens
│ ├── App.tsx # Main app with routing
│ └── main.tsx # Entry point
├── index.html
├── package.json
├── vite.config.ts
└── README.md
-
Create a new JSON file in the
lessons/folder (e.g.,my-lesson.json) -
Use this template:
{
"id": "my-lesson",
"title": "My Lesson Title",
"theme": "kpop",
"difficultyLevel": "A0",
"estimatedMinutes": 15,
"vocabulary": [
{
"id": "word1",
"english": "Hello",
"croatian": "Bok",
"image": "/assets/images/hello.png",
"audio": "/assets/audio/hello.mp3"
}
],
"dialogueCharacter": {
"name": "Luna",
"avatar": "/assets/images/kpop-character.png",
"theme": "kpop"
},
"dialogueTree": [
{
"id": "start",
"message": {
"id": "m1",
"speaker": "Luna",
"text": "Hello! Ready to learn?"
},
"choices": [
{
"id": "c1",
"text": "Yes!",
"nextMessageId": "next-node-id"
}
]
}
],
"games": [
{
"type": "flashcard",
"vocabulary": ["word1"]
},
{
"type": "multiple-choice",
"vocabulary": ["word1"],
"settings": {
"mode": "word-to-translation"
}
},
{
"type": "dialogue",
"dialogueStartId": "start"
}
]
}- Save the file and reload the app—the lesson will appear automatically!
- id: Unique identifier (lowercase-with-dashes)
- theme:
kpop,harry_potter,skiing, orgeneral - difficultyLevel:
A0(beginner),A1, orA2 - vocabulary: Array of words with English, Croatian translation, optional image and audio paths
- games: Array specifying which game types to use in the lesson
- Add image files to
assets/images/ - Reference them in lesson JSON:
"/assets/images/filename.png" - Supported formats: PNG, JPG, SVG
- Add audio files to
assets/audio/ - Reference them in lesson JSON:
"/assets/audio/filename.mp3" - Supported formats: MP3, WAV, OGG
Note: Audio files are not included in this repository. You'll need to:
- Record your own audio for vocabulary words
- Use text-to-speech tools to generate audio
- Source royalty-free audio files
Dialogues use a branching tree structure where each node has:
- A message from a character
- Optional choices leading to other nodes
Example dialogue tree:
"dialogueTree": [
{
"id": "start",
"message": {
"id": "m1",
"speaker": "Luna",
"text": "Hello! How are you?"
},
"choices": [
{ "id": "c1", "text": "I'm good!", "nextMessageId": "response-good" },
{ "id": "c2", "text": "I'm tired", "nextMessageId": "response-tired" }
]
},
{
"id": "response-good",
"message": {
"id": "m2",
"speaker": "Luna",
"text": "That's great to hear!"
}
// No choices = end of conversation
}
]- flashcard: Vocabulary flashcards with flip animation
- multiple-choice: Quiz with 4 options
- dialogue: Interactive conversation with branching paths
- drag-and-drop: Match words to pictures (coming soon)
- memory: Memory card matching game (coming soon)
- letter-scramble: Spell words by arranging letters (coming soon)
- fill-in-the-gap: Complete sentences (coming soon)
- voice-lesson: Audio-based lessons with comprehension questions (coming soon)
Access the tutor dashboard at /tutor:
- Default PIN:
1234 - Features:
- View usage statistics (time, streaks, points)
- See recent activity (last 7 days)
- Identify difficult words (high error rate)
- Export progress as JSON or Markdown
To change the PIN, edit the default value in src/services/storage.ts (line with pin: '1234').
-
Update
vite.config.tsbase path:base: '/ElisEnglish/', // Your repo name
-
Build and deploy:
npm run build # Upload dist/ folder to GitHub Pages
- Connect your repository to Netlify
- Build command:
npm run build - Publish directory:
dist
The app works on any static file host:
- Vercel
- Cloudflare Pages
- Firebase Hosting
- Any web server
Just upload the dist/ folder after running npm run build.
Edit src/services/storage.ts:
profile: {
name: 'YourName', // Change this
nativeLanguage: 'Croatian',
targetDailyMinutes: 30
}-
Add theme colors in
src/styles/design-tokens.css:[data-theme="your-theme"] { --color-primary: #yourcolor; --color-secondary: #yourcolor; /* etc. */ }
-
Update
src/types/lesson.tsto include your theme in theThemetype -
Create lessons with
"theme": "your-theme"
Edit badge definitions in src/services/storage.ts (function getDefaultBadges()).
- Check the console for errors
- Ensure JSON files are valid (use JSONLint.com)
- Verify file paths start with
/lessons/ - Clear browser cache and reload
- Ensure audio files exist in
assets/audio/ - Check file paths in lesson JSON
- Some browsers require user interaction before playing audio
- Try different audio formats (MP3, WAV)
- Check if localStorage is enabled in your browser
- Try a different browser
- Check browser console for errors
This project is created for personal educational use for Eli.
Made with ❤️ for Eli to help her learn English through fun, personalized practice.
Need Help? Check the existing lesson files for examples, or refer to the inline code comments for guidance.