Inworld AI
Overview
Inworld Language Tutor
A conversational language learning app powered by Inworld AI. Practice speaking with an AI tutor, get realtime feedback on your responses, and build vocabulary with auto-generated flashcards. This template can be used to add realtime conversational AI functionality to any application.

Prerequisites
- Node.js (v20 or higher)
- npm
- An Inworld AI account and API key
- An AssemblyAI account and API key (for speech-to-text)
Get Started
Step 1: Clone the Repository
_10git clone https://github.com/inworld-ai/language-learning-node_10cd language-learning-node
Step 2: Install Dependencies
_10npm install
This installs dependencies for the root, backend, and frontend automatically.
Step 3: Configure Environment Variables
Create a backend/.env file:
_10INWORLD_API_KEY=your_inworld_base64_key_10ASSEMBLY_AI_API_KEY=your_assemblyai_key
| Service | Get Key From | Purpose |
|---|---|---|
| Inworld | platform.inworld.ai | AI conversations (Base64 API key) |
| AssemblyAI | assemblyai.com | Speech-to-text |
Step 4: Run the Application
For development (with auto-reload on file changes):
_10npm run dev
This starts both the backend (port 3000) and frontend dev server (port 5173) concurrently.
For production:
_10npm run build_10npm start
Step 5 (Optional): Set Up Supabase for Auth & Memory
Without Supabase, the app works in anonymous mode using localStorage.
a) Create a Supabase project at supabase.com
b) Push the database schema:
_10npx supabase login_10npx supabase link --project-ref YOUR_PROJECT_REF_10npx supabase db push
This creates all tables, indexes, RLS policies, and the match_memories function for semantic search.
Find your project ref in the Supabase dashboard URL: supabase.com/dashboard/project/YOUR_PROJECT_REF
c) Add Supabase variables to backend/.env:
_10SUPABASE_URL=https://YOUR_PROJECT.supabase.co_10SUPABASE_SECRET_KEY=your_secret_key
d) Create frontend/.env.local:
_10VITE_SUPABASE_URL=https://YOUR_PROJECT.supabase.co_10VITE_SUPABASE_PUBLISHABLE_KEY=your_anon_key
Find these in: Supabase Dashboard > Settings > API
Repo Structure
_30language-learning-node/_30├── backend/_30│ ├── src/_30│ │ ├── __tests__/ # Backend unit tests_30│ │ ├── config/ # Language, LLM & server configuration_30│ │ ├── graphs/ # Inworld Runtime conversation graphs_30│ │ │ ├── configs/ # Graph JSON configurations_30│ │ │ └── nodes/ # Custom graph nodes_30│ │ ├── helpers/ # Audio utils, connection management_30│ │ ├── prompts/ # Nunjucks prompt templates_30│ │ ├── services/ # Server components (WS handler, API routes)_30│ │ ├── types/ # TypeScript types_30│ │ ├── utils/ # Logger_30│ │ └── server.ts # Entry point_30│ └── vitest.config.ts # Backend test config_30├── frontend/_30│ ├── src/_30│ │ ├── __tests__/ # Frontend unit tests_30│ │ ├── components/ # React components_30│ │ ├── config/ # Language configuration_30│ │ ├── context/ # App state & auth_30│ │ ├── hooks/ # Custom React hooks_30│ │ ├── services/ # WebSocket client, audio, storage_30│ │ ├── styles/ # CSS_30│ │ └── types/ # TypeScript types_30│ └── vitest.config.ts # Frontend test config_30├── supabase/_30│ └── migrations/ # Database schema_30├── render.yaml # Render deployment config_30└── package.json # Monorepo scripts
Architecture
The app uses a real-time audio streaming architecture:
- Frontend captures microphone audio and streams it via WebSocket
- Backend processes audio through an Inworld Runtime graph:
- AssemblyAI handles speech-to-text with voice activity detection
- LLM generates contextual responses in the target language
- TTS converts responses back to audio
- Flashcards are auto-generated from conversation vocabulary
- Response feedback provides grammar and usage corrections
Memory System
When Supabase is configured, the app stores and retrieves user memories using semantic search:
- Automatic memory creation: Every few conversation turns, the system extracts memorable facts
- Semantic retrieval: Relevant memories are retrieved using vector similarity search (pgvector)
- Personalized responses: The AI uses retrieved memories to personalize conversations
Memory types:
learning_progress: Vocabulary struggles, grammar patterns, learning achievementspersonal_context: Interests, goals, preferences shared by the user
Without Supabase, the app works in anonymous mode using localStorage (no memory persistence).
Environment Variables Reference
| Variable | Required | Description |
|---|---|---|
INWORLD_API_KEY | Yes | Inworld AI Base64 API key |
ASSEMBLY_AI_API_KEY | Yes | AssemblyAI API key |
PORT | No | Server port (default: 3000) |
LOG_LEVEL | No | trace, debug, info, warn, error, fatal (default: info) |
NODE_ENV | No | Set to production for production log format |
ASSEMBLY_AI_EAGERNESS | No | Turn detection: low, medium, high (default: high) |
SUPABASE_URL | No | Supabase project URL (enables memory feature) |
SUPABASE_SECRET_KEY | No | Supabase secret key (for backend memory storage) |
Testing
_11# Run all tests (backend + frontend)_11npm test --prefix backend_11_11# Backend tests only_11npm run test:backend --prefix backend_11_11# Frontend tests only_11npm test --prefix frontend_11_11# Watch mode (backend)_11npm run test:watch --prefix backend
Tests cover critical paths: audio conversion, language configuration, storage persistence, and flashcard deduplication.
Troubleshooting
Bug Reports: GitHub Issues
General Questions: For general inquiries and support, please email us at support@inworld.ai
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines on how to contribute to this project.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Details
Third-party integrations and docs are managed by Supabase partners.


