English Core Speaking
LiveA full-stack English speaking practice service: a NestJS backend and Vue 3 frontend, with OAuth-based sign-in and an external AI/LLM API integration for evaluating spoken responses.
Role: Sole designer and implementer.
- NestJS
- Vue 3
- PostgreSQL
- Prisma
- OAuth
- Kubernetes / k3s
Problem
Practicing spoken English needs fast, structured feedback, not just a transcript. That means integrating a real-time or near-real-time evaluation step into an otherwise ordinary CRUD-shaped product, without the AI dependency becoming a single point of failure for the whole product.
Why it matters
This project is the counterpart to RelayHub: a real, user-facing product rather than an integration lab, exercising ordinary full-stack concerns — auth, data modeling, deployment — at production scale rather than as a demo.
Architecture
A NestJS backend exposes a REST API over PostgreSQL via Prisma; a Vue 3 frontend consumes it. OAuth handles sign-in so the product never stores credentials itself. Spoken-response evaluation is delegated to an external AI/LLM API, called from the backend as a bounded, isolated dependency rather than something the frontend talks to directly. The whole stack is built and deployed as containers on the same k3s cluster as this site.
Key engineering decisions
- NestJS + Prisma for the backend to keep the data-access layer typed and migration-driven rather than hand-rolled SQL.
- OAuth for authentication instead of a custom credential store, removing an entire class of security responsibility from the product.
- The AI/LLM evaluation call is isolated behind a backend boundary, not called from the client, so its latency and failure behavior can be controlled centrally.
Failure handling
- The external AI/LLM dependency is treated as a fallible external call with its own latency and error budget, not assumed to always succeed.
Observability
- Standard backend request logging and k3s-level health checks; no dedicated metrics dashboard for this project yet (unlike RelayHub).
Result
Live in production on the same Hetzner k3s cluster that hosts this site, serving real practice sessions.
What I learned
- Treating an external AI API as an ordinary external dependency (with timeouts, error handling, and a fallback UX) matters more for reliability than the specific model or provider chosen.