Ezen IELTS AI — Your Personal IELTS Coach, Built for Everyone
Inspiration
In Vietnam, IELTS is a lifelong gatekeeper.
Students need it for university, professionals need it for careers, and families need it for immigration.
Yet quality preparation remains expensive, with private tutors often charging $20–50/hour. Meanwhile, most online tools are built in English, for English-fluent users.
We observed real learners — people with limited English proficiency and limited technical experience — struggling to navigate the very platforms designed to help them.
That became our founding constraint, written into our codebase as a hard rule:
Every screen must be understandable in simple Vietnamese, a first-time user must complete a core task in under 3 minutes, and every feature must map to a measurable band-score improvement.
If a feature passes all tests but fails that standard, it is not finished.
This project also started as a one-person project.
As the scope kept growing — AI grading, payments, quota systems, speech recognition — it became clear that one pair of hands was not enough.
Old university classmates joined first, then students from other universities.
What began as a solo side project became a team united by the same goal:
Making IELTS preparation accessible to every Vietnamese learner.
What It Does
Ezen IELTS AI is a full-stack IELTS practice platform powered by an AI examiner.
Writing Practice
Users can submit essays and receive instant AI grading with detailed band-aligned feedback.
The system evaluates writing criterion-by-criterion and then synthesizes the result into a final report.
Speaking Practice
Users can record answers directly in the browser using the Web Speech API and MediaRecorder.
No plugins are required, and no uploads to third-party services are needed.
The AI examiner grades the transcript across IELTS criteria, with a manual transcript fallback for unsupported browsers.
Listening Practice
Users can practice with AI-generated listening exercises, guided questions, and structured feedback flows.
Audio tracks are served from Cloudflare R2 object storage.
Quick Test
A 5-minute no-signup assessment that allows users to experience value before creating an account.
AI Chat
A streaming IELTS assistant built on a LangGraph agent pipeline, including:
- Keyword-first intent routing
- LLM fallback only when the intent is ambiguous
- Prompt-injection guardrails
- Streaming sanitizer that scrubs model/provider leaks
- Protection even when a forbidden term is split across two stream chunks
Knowledge Ingestion API
A stateless document-ingestion service that chunks content and returns 1024-dimensional Mistral embeddings directly.
No vector database is required to maintain.
Personalized Learning Roadmap
Daily study plans tailored to the user's current level and target IELTS band score.
Fair Usage System
Transparent Guest → Free → Student plans featuring:
- Usage tracking
- Remaining quota visibility
- Reset countdowns
- PayOS payment integration
- Webhook checksum verification
- Async plan activation via Pub/Sub
- Daily quota resets at 5:00 AM Vietnam Time
Vietnamese-First Experience
The entire product is designed in plain Vietnamese, with full English i18n via next-intl.
We actively rewrote technical phrases such as:
AI định hướng việc học
into:
Học đúng bài, đúng lúc — AI lo cho bạn
We also enforced a strict UX principle:
One primary action per screen.
How We Built It
| Layer | Technology |
|---|---|
| Frontend | Next.js 16 + React 19, App Router, Server Components, Server Actions, React Compiler |
| Backend | Encore.dev + TypeScript microservice-style services |
| Database | PostgreSQL + Drizzle ORM |
| AI | Mistral API, SSE streaming via api.streamOut, LangChain/LangGraph agent pipeline |
| Speech | Web Speech API, SpeechRecognition, SpeechSynthesis, MediaRecorder |
| Payments | PayOS + Encore Pub/Sub |
| Storage | Cloudflare R2 for audio tracks and writing task images |
| Styling | Tailwind CSS v4 + shadcn/ui |
| Authentication | Custom JWT with HS512 + bcrypt |
| Testing & Quality | Vitest + Playwright E2E + Biome |
Architecture
The backend is organized as independent Encore services, with each service owning a specific business domain:
- Authentication
- AI Chat with LangGraph agent
- Writing Evaluation
- Speaking Evaluation
- Listening Practice
- Quick Test
- Pricing & Quotas
- Payments with PayOS + Pub/Sub
- Learning Roadmap
- Knowledge Ingestion
On the frontend:
- Server Components render by default
- Mutations are handled through Server Actions
- No ad-hoc API routes are used
Usage tracking, rate limiting, and plan enforcement are centralized in a dedicated pricing service.
This ensures every AI feature shares a consistent quota system.
Challenges We Ran Into
1. Metering AI Usage Without Token Data
Mistral's streaming API does not return token counts, yet our pricing model depends on usage tracking.
We built a custom estimation strategy:
tokens ≈ response_length / 4
This was integrated into a centralized checkAndIncrementUsage service with:
- Daily token limits
- Hourly request windows
- Automatic resets at 05:00 Vietnam Time
2. Defending the AI Examiner Against Prompt Injection
Users will try to make the AI reveal its system prompt, its model name, or grade them a Band 9 for free.
We built a deterministic guardrail layer instead of relying on the model to refuse.
This includes:
- A keyword-based injection detector that short-circuits inside the agent graph
- Refusal responses that stream back without ever calling the LLM
- A stateful stream sanitizer that scrubs provider/model names from responses
- A carry-over window that catches forbidden terms split across stream chunks, such as
"Mist"+"ral" - A circuit breaker around Mistral:
- 5 failures within 60 seconds
- Open state
- Half-open recovery
- An LRU plan cache to absorb rapid retries
3. Streaming That Freezes
Chat streams occasionally stalled when WebSocket connections closed mid-response.
To solve this, we added:
- Explicit close-event handling
- Recovery logic
- Frontend logging
- Backend logging
This significantly improved long-response reliability.
4. Server Components Are Unforgiving
A single thrown exception during data fetching could crash an entire server-rendered page.
We redesigned our API layer around safer behavior:
apiFetchnever throws- Typed error responses are returned everywhere
- Token and cookie retrieval are explicit
This eliminated an entire class of dashboard crashes.
5. Embeddings Without Database Bloat
Our first knowledge-base implementation stored embeddings with pgvector.
The database grew rapidly and became costly to maintain.
We replaced it with a completely stateless /knowledge ingestion API that chunks documents and returns embeddings directly.
The result:
- Lower costs
- Simpler architecture
- One less stateful system to operate
6. Designing for Non-Technical Users
The biggest UX problem was not aesthetics.
Users consistently struggled to answer:
What am I doing, and how does this help me improve my IELTS score?
We responded by:
- Reducing copy density by around 30%
- Removing unnecessary English terminology
- Showing meaningful progress within the first 60 seconds
7. Testing AI End-to-End
Real JWT authentication plus non-deterministic AI responses made E2E testing fragile.
We built a dedicated testing mode:
E2E_MOCK_AUTH=1
This mode is only activatable when:
NODE_ENV === "test"
It allows Playwright to execute complete user journeys:
Login
→ Generate Practice
→ Receive Feedback
→ View Results
This works without requiring real credentials and without any mock path ever shipping to production.
What We Learned
User Outcomes Beat Feature Count
Our definition of "done" now includes validation from non-technical users, not just passing automated tests.
Streaming AI Products Need Cost Infrastructure
If your AI provider does not meter usage, you must build that capability yourself:
- Idempotently
- Transactionally
- Transparently
Guardrails Must Be Deterministic
A model can be talked out of its instructions.
A regex cannot.
Putting injection defense and leak sanitization outside the LLM was the only approach that survived real users.
Stateless Beats Clever
Both our embedding-service redesign and our never-throw API strategy reinforced the same lesson:
Predictable systems outperform clever systems in production.
Plain Language Is a Product Feature
Changing:
Band Score
to:
Điểm IELTS mục tiêu
had a bigger impact on user activation than several visual redesigns combined.
A Growing Scope Needs a Growing Team
Starting solo forced ruthless prioritization.
Growing into a team — old classmates and students from different universities — forced something harder:
Writing rules down.
Our founding constraint went from a habit in one person's head to a documented standard every contributor builds against.
That transition, more than any framework, is what allowed the project to scale.
Built With
- cloudflare-r2
- drizzle-orm
- encore.dev
- langchain
- langgraph
- mistral-ai
- next.js
- payos
- playwright
- postgresql
- python
- react
- shadcn-ui
- tailwindcss
- typescript
- vercel
- vitest
- web-speech-api
- zod
- zustand
Log in or sign up for Devpost to join the conversation.