Discover, rate, remember.
A production-style React + Spring Boot movie application with explainable discovery,
an AI Movie Concierge, OpenSearch, full-stack observability, and k3s GitOps.
Live Demo · Backend API · Movie Concierge · Agent Roadmap · Operations · Kubernetes Setup
IMDb Clone is a full-stack movie catalog built as a production-style reference application. It goes beyond a CRUD demo: movies are stored in PostgreSQL, searched through OpenSearch, served with poster and backdrop media from S3-compatible object storage, and discovered conversationally through a Python AI agent that calls Java-owned movie capabilities over MCP. The complete system is deployed to a self-hosted Kubernetes cluster through GitOps.
The project is intentionally kept close to a real web application architecture: generated API clients, explicit seed data, server-side session authentication, automated CI/CD, infrastructure manifests, and local developer workflows are all part of the repository.
- Modular Spring Boot backend with PostgreSQL, Flyway, Spring Security, JDBC sessions, CSRF protection, OpenAPI, and Testcontainers.
- React frontend with TypeScript, Material UI, TanStack Query, generated Axios clients, and feature-oriented structure.
- Python 3.14 Movie Concierge with FastAPI, Pydantic AI, typed streaming events, bounded tool use, deterministic evals, cost limits, and Java-owned MCP tools.
- Password, Google, GitHub, and WebAuthn passkey login methods attached to one account model.
- Hybrid lexical and semantic OpenSearch retrieval plus reusable, explainable recommendation strategies.
- S3-compatible media storage through RustFS for movie posters, backdrops, and profile images.
- Repeatable local development with Docker Compose, lightweight seed data, and explicit search reindexing.
- Self-hosted k3s deployment with Argo CD, Traefik ingress, cert-manager HTTPS, and encrypted GitOps secrets.
- Production observability with anonymous browser Web Vitals, Prometheus metrics, Loki logs, Tempo traces, continuous Java/Python profiles in Pyroscope, Grafana drilldowns, Kubernetes Events, and privacy-safe trace propagation.
- Left-shift build safeguards across Java, TypeScript, architecture, API contracts, tests, and dependency resolution.
- Version-gated release workflow that builds Docker images and updates Kubernetes image digests from one
VERSIONfile.
Runtime containers:
flowchart LR
browser["Browser"]
model["OpenAI model"]
subgraph app["IMDb Clone"]
frontend["React Frontend"]
agent["Python Movie Concierge<br/>FastAPI + Pydantic AI"]
backend["Spring Boot API"]
end
subgraph data["Data and media"]
postgres[("PostgreSQL")]
opensearch[("OpenSearch")]
rustfs[("RustFS / S3")]
end
browser --> frontend
frontend -- "REST" --> backend
frontend -- "chat + SSE" --> agent
frontend --> rustfs
agent -- "bounded model calls" --> model
agent -- "protected MCP tools" --> backend
backend --> postgres
backend --> opensearch
backend --> rustfs
postgres -. "explicit reindex" .-> opensearch
The backend owns the application domain and persists movie, identity, account, and engagement data in PostgreSQL. OpenSearch is used as a derived search index and can be rebuilt explicitly from PostgreSQL. RustFS provides S3-compatible object storage for public movie media and private account uploads. The React frontend talks to the backend through generated API clients and loads public media through the object-storage host. Its Movie Concierge surface streams typed events from the Python service; Python can discover movies only through protected MCP tools owned by Java and never queries PostgreSQL or OpenSearch directly.
Observability pipeline:
flowchart LR
subgraph sources["Telemetry sources"]
workloads["Kubernetes workloads"]
events["Kubernetes Events"]
k3s["k3s systemd service"]
traefik["Traefik access logs"]
frontendTelemetry["React browser signals"]
agentTelemetry["Python Movie Concierge"]
backendTelemetry["Spring Boot API"]
llamaTelemetry["llama.cpp embeddings"]
end
subgraph stores["Collection and storage"]
alloy["Grafana Alloy"]
prometheus[("Prometheus<br/>metrics · 7 days")]
loki[("Loki<br/>logs · 7 days")]
tempo[("Tempo<br/>traces · 3 days")]
pyroscope[("Pyroscope<br/>CPU + allocation profiles")]
end
grafana["Grafana<br/>dashboards + Drilldown"]
workloads -- "pod logs" --> alloy
events -- "event stream" --> alloy
k3s -- "journal" --> alloy
traefik -- "privacy-filtered logs" --> alloy
frontendTelemetry -- "anonymous bounded batches" --> backendTelemetry
agentTelemetry -- "OTLP traces" --> alloy
backendTelemetry -- "OTLP traces" --> alloy
agentTelemetry -- "CPU + allocation samples" --> pyroscope
backendTelemetry -- "JFR CPU + allocation + lock samples" --> pyroscope
alloy -- "logs" --> loki
alloy -- "traces" --> tempo
agentTelemetry -- "bounded metrics" --> prometheus
backendTelemetry -- "Actuator metrics" --> prometheus
llamaTelemetry -- "native metrics" --> prometheus
prometheus --> grafana
loki --> grafana
tempo --> grafana
pyroscope --> grafana
Alloy collects logs and privacy-safe Python/Java traces without storing them itself. Prometheus scrapes bounded application, browser-experience, embedding, and cluster metrics. Browser telemetry contains only fixed event categories, timings, Web Vital ratings, and coarse API outcomes—never URLs, user/session IDs, error messages, stacks, or search text. Grafana provides the shared query and dashboard surface over Prometheus, Loki, Tempo, and Pyroscope; the detailed retention, privacy, and access contracts are documented in the observability guide.
Delivery pipeline:
flowchart LR
version["VERSION bump"]
ci["GitHub Actions<br/>Java + React + Python gates"]
registry["Docker Hub<br/>backend + frontend + agent images"]
manifests["Kubernetes manifests"]
argocd["Argo CD"]
cluster["k3s home cluster"]
ingress["Traefik + cert-manager"]
public["Public HTTPS hosts"]
version --> ci
ci --> registry
ci --> manifests
manifests --> argocd
registry --> cluster
argocd --> cluster
cluster --> ingress
ingress --> public
The public deployment runs on a Minisforum UM560 home server as a single-node k3s cluster.
- Frontend: https://imdb-clone.the-coding-lab.com/
- Backend API: https://backend.imdb-clone.the-coding-lab.com/
- Movie media: https://object-storage.imdb-clone.the-coding-lab.com/
- Grafana: https://grafana.imdb-clone.the-coding-lab.com/
Kubernetes manifests and home-cluster notes live in infrastructure/kubernetes and infrastructure/clusters/home. Private database, search, storage, metrics, log, trace, and Argo CD access is documented in the production operations runbook.
| Area | Technology |
|---|---|
| Backend | Java 25, Spring Boot 4, Spring Security, Spring Data JPA, Flyway |
| Frontend | React 19, TypeScript 6, Material UI 9, TanStack Query, Vite |
| Agent | Python 3.14, FastAPI, Pydantic AI 2.31, Pydantic Evals, uv, MCP, SSE |
| Data | PostgreSQL 18, OpenSearch 3 |
| Media | RustFS, S3-compatible object storage, WebP poster/backdrop variants |
| API | OpenAPI spec, generated Axios client |
| Authentication | Spring Session JDBC, CSRF, password login, Google/GitHub OAuth2, WebAuthn passkeys |
| Testing | JUnit, Spring Boot Test, Testcontainers, jqwik, JaCoCo, Vitest, React Testing Library, Playwright |
| Build safety | Error Prone, NullAway/JSpecify, strict TypeScript, typed ESLint, API-contract drift checks |
| Delivery | Docker, GitHub Actions, k3s, Argo CD, Traefik, cert-manager, SOPS/age |
| Observability | OpenTelemetry, Grafana Alloy, Prometheus, Loki, Tempo, Pyroscope, Grafana |
- Explore a progressive, session-stable discovery feed with three featured movies and curated carousel sections.
- Ask the Movie Concierge by text and receive grounded answers plus automatically rendered movie cards.
- Ask Tonight Mode for three diverse, explained picks constrained by mood, runtime, genres, era, and watched history.
- Search through hybrid title/metadata and semantic retrieval with catalog filters and measured ranking foundations.
- View backdrop-led movie pages with metadata, ratings, trailers, similar movies, sharing, and community comments.
- Register and sign in with a password, Google, GitHub, or a passkey through hardened server-side sessions.
- Manage account settings, profile images, passkeys, ratings, watchlists, and authored comments.
- Review server-backed rating insights and use the watchlist's explainable three-choice decision helper.
- Rebuild the OpenSearch index from PostgreSQL through an explicit admin flow.
- Seed local and production-like environments with versioned movie/media images.
- Java 25
- Docker with Compose
- Node.js 24 and Yarn
- Python 3.14 and uv for the Movie Concierge
- Make
The root Makefile is a command index for common workflows. It assumes these tools are installed
locally; you can check the local development prerequisites with:
make check-local-toolsRun make help to see all grouped targets.
Start PostgreSQL, OpenSearch, and RustFS:
make docker-compose-dev-upThe Docker Compose setup includes a one-shot RustFS init container that creates the imdb-clone bucket and makes
imdb-clone/movies/* publicly readable.
In a second terminal:
./gradlew bootRunThe backend runs on http://localhost:8080. Flyway creates the schema on startup.
With the backend and Docker Compose services running:
make seed-local-users
make seed-light SEED_VERSION=2026-05-17
make reindex-local-searchThe lightweight seed contains 250 movies and matching WebP media. The seed is idempotent, so rerunning it updates movie and media rows without wiping local user data. The full seed pipeline can build larger datasets from IMDb and TMDB data; details live in infrastructure/movie-seed.
In a third terminal:
cd frontend
yarn install
yarn run build:moviesGen
yarn startThe frontend runs on http://localhost:3000.
For deterministic UI work without Java or a provider key:
make agent-sync
make run-agent-fakeThe real local agent reads its OpenAI key only from the ignored
.secrets/movie-concierge.local.env file and starts with make run-agent. Follow the complete
credential, budget, MCP, eval, and safety instructions in the
Movie Concierge README; never export or commit the key.
Detailed workflow docs:
- Development Guide for local setup, env vars, smoke checks, and troubleshooting.
- Movie Concierge for Python setup, runtime contracts, evals, and production guardrails.
- Movie Concierge Architecture for the accepted product and trust boundaries.
- Movie Concierge Roadmap for capabilities, personal actions, external knowledge, safety, scaling, and voice milestones.
- Production Operations for URLs, private tunnels, DBeaver, logs, traces, and incidents.
- Agentic Engineering for agent workflow, task templates, verification, and review.
- Left-Shift Engineering Roadmap for planned compiler, type, test, and agent-feedback experiments.
- Frontend Design System for theme tokens, shared layout primitives, and UI consistency.
- Product Roadmap for the long-term movie detail and discovery vision.
- Agent Fast-Start for repo terminology, ownership, safety rules, and definition of done.
Useful commands from the repository root:
make help # list grouped workflow targets
./gradlew test # fast backend tests
./gradlew integrationTest # backend integration tests
./gradlew build jacocoTestReport # backend CI-equivalent check
./gradlew spotlessApply # format backend code
cd frontend && yarn typecheck # browser, Vite, and Playwright TypeScript checks
cd frontend && yarn lint # type-aware frontend linting
cd frontend && yarn test # frontend unit and component tests
cd frontend && yarn build # frontend production build
make verify-agent # Python formatting, types, architecture, tests, and deterministic evals
make verify-observability-charts # render Loki, Tempo, Pyroscope, and Alloy; validate Alloy configuration
make verify-kubernetes-schema # render and validate the complete home-cluster GitOps treeThe frontend API client is generated from the backend OpenAPI spec. If backend contracts change, start the backend and regenerate the client:
cd frontend
yarn run updateOpenApiSpec
yarn run build:moviesGenGenerated client files under frontend/src/client/movies/generator-output should not be edited manually.
CI also compares the backend's runtime OpenAPI document with the checked-in frontend specification, ignoring only the
environment-specific server URL, so contract drift fails before client generation can silently use stale types.
Every pull request targeting master runs backend verification plus frontend client generation, linting, tests, type
checking, and a production build. The same gates run again on merged master commits. Application releases are
controlled by the root VERSION file. A version bump merged to master triggers the CD workflow, which:
- runs backend, frontend, and deterministic agent checks,
- builds Linux AMD64 backend, frontend, and agent Docker images,
- pushes versioned images to Docker Hub,
- resolves immutable image digests,
- updates the home-cluster Kubernetes manifests on a dedicated release branch,
- opens a deployment pull request containing the three immutable image digests,
- lets Argo CD reconcile the live cluster only after that pull request passes CI and is merged.
Infrastructure-only changes under infrastructure/clusters/home can be deployed through a normal reviewed pull
request without publishing new application images.
src/main/java/com/thecodinglab/imdbclone Spring Boot backend modules
frontend/src React frontend source
agent/src/imdb_agent Python Movie Concierge modules
compose.yaml Local Docker Compose services
infrastructure/clusters/home k3s GitOps manifests
infrastructure/movie-seed Movie and media seed pipeline
docs/operations.md Production access and incident runbook