Team Drops is an AI-assisted language-learning platform. It combines structured learning plans and exercises with generated content, speaking and listening practice, automated feedback, progress tracking, and Keycloak-based authentication.
The repository contains the browser application, three Spring Boot domain services, a FastAPI GenAI service, local Docker infrastructure, Kubernetes Helm charts, and the project documentation.
The repository represents the final integrated project architecture. The local
stack runs through Docker Compose, and the Rancher deployment uses separate
application and monitoring releases. api/openapi.yaml, the Helm values, and
the GitHub Actions workflows are the sources of truth for runtime behavior;
older proposal and diagram files are retained as historical design material.
- User registration, authentication, and profile management
- Language-specific learning plans, lessons, and exercises
- Answer submission, feedback, and progress tracking
- LLM-assisted content generation and retrieval-augmented generation
- Speech-to-text and text-to-speech exercises
- Application metrics, version visibility, dashboards, alerting, and logs
| Component | Responsibility | Technology | Local port | Main dependencies |
|---|---|---|---|---|
| Frontend | Learning interface and authentication flow | React 19, Vite 6, TypeScript 5 toolchain, Nginx | 3000 | Keycloak and the three domain APIs |
| User service | Users and profiles | Spring Boot 3.5, Java 21 | 8081 | PostgreSQL, Keycloak |
| Learning service | Learning plans, lessons, and exercises | Spring Boot 3.5, Java 21 | 8082 | PostgreSQL, Keycloak |
| Progress and feedback service | Answers, generated feedback, and progress | Spring Boot 3.5, Java 21 | 8083 | PostgreSQL, domain services, GenAI service |
| GenAI service | Generation, RAG, speech-to-text, and text-to-speech | Python 3.13, FastAPI | 8084 | Ollama or OpenAI-compatible API, MongoDB, Keycloak |
| Keycloak | Identity and access management | Keycloak 26 | 8090 | Imported team-drops realm |
| PostgreSQL | Relational application data | PostgreSQL 16 | 5433 | Backend services |
| MongoDB | GenAI and retrieval data | MongoDB 7 | 27017 | GenAI service |
| Ollama | Optional local language-model runtime | Ollama | 11434 | GenAI service when local-ollama profile is enabled |
Browser requests use relative paths such as /user-service,
/learning-service, and /progress-service. Vite proxies these paths during
local development, while Nginx and Kubernetes Ingress route them in deployed
environments.
team-drops/
|-- api/ # Central and per-service OpenAPI contracts
|-- backend/
| |-- user-service/
| |-- learning-service/
| `-- progress-feedback-service/
|-- frontend/ # React browser application
|-- genai/ # FastAPI GenAI service
|-- helm/
| |-- team-drops/ # Application chart with Rancher and Azure values
| |-- team-drops-monitoring/ # Monitoring chart with Rancher and Azure values
| `-- ingress-nginx-values-azure.yaml # Azure ingress load-balancer settings
|-- infra/
| `-- azure/ # Future/manual AKS, ACR, network and state Terraform
| `-- bootstrap/ # Remote Terraform-state storage bootstrap
|-- keycloak/ # Local realm export
|-- scripts/
| `-- azure/ # Manual image publishing and AKS deployment scripts
|-- docs/ # Architecture and project documentation
|-- .env.example # Local configuration example
`-- docker-compose.yml # Complete local stack
Requirements:
- Docker with Docker Compose v2
- An OpenAI-compatible external LLM API key in
LLM_API_KEY.
Create your local configuration and start the stack:
cp .env.example .env
docker compose up --buildOn Windows PowerShell, use Copy-Item .env.example .env for the first command.
The default example connects GenAI to an OpenAI-compatible external API using
LLM_PROVIDER=openai, LLM_API_KEY, and LLM_MODEL.
For a local Ollama fallback, set LLM_PROVIDER=ollama and
OLLAMA_BASE_URL=http://ollama:11434 in .env, then start Compose with the
opt-in profile:
docker compose --profile local-ollama up --buildWhen using the local-ollama profile for AI QA, wait for the one-shot
ollama-pull service to finish downloading OLLAMA_MODEL before generating
RAG plans. Otherwise the first GenAI request can fail or time out while the
model is still being pulled.
Useful local endpoints:
| Endpoint | URL |
|---|---|
| Frontend | http://localhost:3000 |
| Keycloak | http://localhost:8090 |
| User health | http://localhost:8081/actuator/health |
| Learning health | http://localhost:8082/actuator/health |
| Progress health | http://localhost:8083/actuator/health |
| GenAI readiness | http://localhost:8084/health |
Stop the stack with docker compose down. Add --volumes only when you
intentionally want to remove the local PostgreSQL, MongoDB, and Ollama data.
.env.example documents the supported local LLM and authentication settings.
The default example uses an OpenAI-compatible provider. Set LLM_API_KEY,
LLM_MODEL, and, when required, LLM_BASE_URL. Never commit real credentials
or add them to Helm values.
Authentication is controlled by AUTH_ENABLED. When enabled, the frontend and
APIs use the team-drops Keycloak realm and client. The local realm is imported
from keycloak/realm-export.json. See
Keycloak authentication for the complete
flow and configuration.
Each backend service has an independent Gradle wrapper. From a service directory, run:
./gradlew buildUse gradlew.bat build on Windows. The services require Java 21.
cd frontend
npm ci
npm run dev
npm run lint
npm run buildSee the frontend guide for proxy and Keycloak settings.
The GenAI project uses uv and Python 3.13 or newer:
cd genai
uv sync --group dev
uv run pytest tests/ -vSee the testing strategy and coverage matrix for the behaviour covered by every backend service, GenAI, frontend, E2E, and CI suite.
api/openapi.yaml is the central API contract. Design API changes there first,
then update the implementation and derived service contracts. Export and check
the contracts with:
bash api/scripts/export_openapi.shOn Windows PowerShell with Git Bash installed:
& "C:\Program Files\Git\bin\bash.exe" api/scripts/export_openapi.shCommit changes to the central contract and affected files under
api/services/. Generated backend interfaces and models are managed by each
service's Gradle OpenAPI task; do not edit generated output manually. The
frontend currently keeps its request layer in frontend/src/api/client.js and
response mapping in frontend/src/api/mappers.js, so contract changes must be
reflected there as well. CI checks that exported OpenAPI specifications remain
in sync.
Kubernetes uses two independently managed Helm releases in the existing
team-drops Rancher namespace:
| Release | Chart | Namespace |
|---|---|---|
team-drops |
helm/team-drops |
team-drops |
team-drops-monitoring |
helm/team-drops-monitoring |
team-drops |
The deployment workflow does not create or modify the Namespace object. Create
team-drops through Rancher with an authorized identity before the first
deployment. Application and monitoring credentials are supplied through GitHub
repository secrets and namespaced Kubernetes Secrets, never committed values.
See the Helm deployment and operations guide for required secrets, rendering, installation, verification, rollback, and troubleshooting commands.
The separately owned team-drops-monitoring release provides:
- Prometheus with seven-day retention and a persistent 2 GiB volume
- Grafana with provisioned Prometheus and Loki datasources and persistent configuration
- A 13-panel Team Drops Overview dashboard for traffic, errors, latency, availability, versions, replicas, restarts, JVM memory, readiness, scrape duration, and active alerts
- A Team Drops Logs dashboard for log volume, errors, and container streams
- Loki with three-day retention on a persistent 2 GiB volume
- Alloy collecting logs only from the
team-dropsnamespace - kube-state-metrics collecting only pod and deployment state from
team-drops, using namespaced read-only RBAC - Alertmanager routing warnings to enabled Slack and email receivers and critical alerts to enabled Slack, email, and PagerDuty receivers
- Four runtime alerts: service down, high error rate, slow responses, and pod restart bursts
The monitoring chart does not manage ResourceQuota or LimitRange because those policies apply to the shared namespace and remain under Rancher administration. The deployment also excludes node-exporter, privileged host access, and node infrastructure dashboards.
| Workflow | Purpose |
|---|---|
backend-ci.yml |
Automatically lints/builds backend; manually runs unit/API integration suites and uploads reports on demand |
frontend-ci.yml |
Runs unit/integration and Playwright E2E tests before building the frontend and image |
genai-ci.yml |
Automatically verifies GenAI contracts/builds its image; manually runs tests and uploads a JUnit report on demand |
docker-publish.yml |
Builds and publishes application images to GHCR |
deploy-kubernetes.yml |
Validates both charts, upgrades the application, and deploys monitoring |
validate-azure.yml |
Validates the future Azure Terraform, Helm, and script files without deploying |
The CI workflows run on relevant pull requests and pushes. Kubernetes deployment runs after a successful main-branch image publication and can also be started manually.
The documentation index groups the architecture, API, authentication, deployment, and historical project material. Key references:
- Frontend/backend API integration
- Keycloak authentication
- Nginx gateway
- Microservice best practices
- Helm deployment and operations
- Future Azure AKS deployment
Historical planning material, including the proposal, diagrams, and product backlog, remains available for project context.