ASAP Poliglota is a mobile app that puts learners in real-world English scenarios — voice or text — and delivers AI-powered feedback after every session.
Every feature is designed around one goal: getting the learner to speak and write more English, in realistic situations, with immediate feedback.
Direct WebRTC connection to OpenAI Realtime API. Sub-second latency, full-duplex audio. The backend never touches the audio stream — only issues ephemeral tokens.
Practice at your own pace with an AI conversation partner. Choose a scenario, pick your level, and the AI adapts vocabulary and complexity accordingly.
After each session, Spring AI sends the transcript to GPT-4o-mini. Returns a score, strengths, recurring issues, and one actionable improvement tip.
Airport, workplace, hospital, social settings. Each scenario has curated sub-situations. Users practice vocabulary that actually matters for their lives.
Weekly practice frequency, score trends, best recent performance, and recurring weak points — all surfaced on a clean dashboard with no data noise.
Passwordless access through secure Firebase email links, plus plan-based limits enforced via Redis TTL buckets and Hotmart webhooks for the billing lifecycle.
Two domain microservices own customer and conversation data. Firebase provides identity, while a dedicated notification service handles SMTP delivery only.
Infrastructure: Docker · Nginx (reverse proxy / API gateway) · Jenkins CI/CD · VPS
The mobile app posts the normalized email to /subscriptions/auth/login-link. The subscription service checks eligibility and applies rate limiting without revealing whether the account exists.
Firebase Admin generates a temporary, one-time link. FreeMarker renders branded HTML and notifications-app delivers it through SMTP. The public API never returns the link.
An Android App Link opens the app, which calls signInWithEmailLink. The resulting Firebase ID Token is sent as Bearer, with one forced refresh and retry after a 401.
The mobile app never calls notifications-app directly, and the delivery service never receives Firebase Admin credentials or decides login eligibility. Initial provisioning also triggers one idempotent welcome email with a fresh first-access link; email failures never roll back customer provisioning.
Production-grade choices for each layer, with independent deployability as the guiding constraint.
| Language | Java 21 |
| Framework | Spring Boot 3.5.8 |
| AI | Spring AI 1.1.2 gpt-4o-mini |
| Database | PostgreSQL Flyway |
| Cache | Redis |
| Mapping | MapStruct 1.6.3 |
| Auth | Firebase ID Token OAuth2 RS JWK Validation |
| HTTP Client | OpenFeign |
| Testing | JUnit 5 Testcontainers JaCoCo |
| Language | Java 21 |
| Framework | Spring Boot 3.5.8 |
| Database | PostgreSQL Flyway Hibernate Types |
| Auth | Firebase Auth Admin SDK ID Token |
| FreeMarker notifications-app SMTP | |
| Billing | Hotmart Webhooks |
| HTTP Client | OpenFeign |
| Testing | JUnit 5 Testcontainers JaCoCo |
| Docs | springdoc-openapi |
| Language | Java 21 |
| Framework | Spring Boot 3.4.3 |
| Spring Mail SMTP | |
| API | Spring Web Bean Validation |
| Security | Spring Security Internal API |
| Operations | Actuator Docker |
| Responsibility | Pre-rendered email delivery only |
| Framework | React Native 0.83 |
| Language | TypeScript 5.8 |
| Auth | Firebase Auth Email Link Android App Links |
| API Security | ID Token Bearer 401 Refresh |
| Monitoring | Firebase Crashlytics |
| Voice | react-native-webrtc |
| HTTP | Axios 1.13 |
| Navigation | React Navigation 7 |
| UI | Lottie lucide-react-native |
| Testing | Jest 29 @testing-library/rn |
| Containers | Docker |
| Gateway | Nginx |
| CI/CD | Jenkins |
| Deploy | VPS |
| Identity | Firebase Authentication |
| notifications-app SMTP | |
| Build | Maven |
Seven decisions that shaped the architecture — each one made to solve a real constraint, not to add complexity.
Rather than proxying audio through our servers, the app gets a short-lived token and opens a WebRTC session directly with OpenAI. This eliminates infrastructure audio latency, avoids storing sensitive audio data, and drastically reduces bandwidth costs. The backend's only role in a voice session is minting the token and evaluating the transcript afterward.
Each microservice owns its own PostgreSQL database. The conversation service never reads the subscription DB directly — it calls the subscription service via Feign when it needs plan or level data. This enforces proper domain boundaries and makes each service independently deployable and testable.
Usage limits (voice minutes, text conversations, AI evaluations per plan) are tracked in Redis with TTL-based windows that reset on schedule. This avoids expensive DB writes on every user action and enables sub-millisecond limit checks at the API layer without adding a caching proxy.
AI evaluation prompts are stored as Flyway repeatable migrations (R__prompts.sql). This allows prompt iteration — adjusting tone, evaluation criteria, output format — without code changes or redeployment. A DB migration is all that's needed, keeping prompt engineering fully decoupled from application releases.
Both services spin up real PostgreSQL and Redis instances in CI via Testcontainers — no mocks, no in-memory substitutes. JaCoCo merges unit and integration coverage into a single report, so coverage numbers actually reflect what runs in production. The test suite runs with mvn verify, not just mvn test.
Firebase remains the identity provider, while customer-subscription owns email normalization, eligibility, anti-abuse controls, anti-enumeration responses, branding, and delivery orchestration. Every request creates a temporary, one-time link that is sent by notifications-app and never returned by the public endpoint.
Crashlytics captures native and fatal JavaScript failures plus selected handled technical errors. Reports contain only controlled operation, reason, and optional HTTP status — never email, Firebase UID or ID Token, Authorization headers, magic links, oobCode, payloads, raw responses, SDP, ephemeral keys, audio, messages, or transcripts.
From splash to AI feedback — every screen designed for clarity and focus on the learning task.