Discover, rate, remember.
A production-style React + Spring Boot movie application with explainable discovery,
OpenSearch, object storage, and k3s GitOps.
Live Demo · Backend API · 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 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.
- 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.
- 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"]
subgraph app["IMDb Clone"]
frontend["React Frontend"]
backend["Spring Boot API"]
end
subgraph data["Data and media"]
postgres[("PostgreSQL")]
opensearch[("OpenSearch")]
rustfs[("RustFS / S3")]
end
browser --> frontend
frontend --> backend
frontend --> rustfs
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.
Delivery pipeline:
flowchart LR
version["VERSION bump"]
ci["GitHub Actions"]
registry["Docker Hub"]
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/
Kubernetes manifests and home-cluster notes live in infrastructure/kubernetes and infrastructure/clusters/home.
| 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 |
| 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 |
- Explore a progressive, session-stable discovery feed with three featured movies and curated carousel sections.
- 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
- 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.
Detailed workflow docs:
- Development Guide for local setup, env vars, smoke checks, and troubleshooting.
- 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 buildThe 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 push runs backend verification plus frontend client generation, linting, tests, type checking, and a production
build. Application releases are controlled by the root VERSION file. A version bump on master also
triggers the CD workflow, which:
- runs backend and frontend checks,
- builds Linux AMD64 backend and frontend Docker images,
- pushes versioned images to Docker Hub,
- resolves immutable image digests,
- updates the home-cluster Kubernetes manifests,
- lets Argo CD reconcile the live cluster from Git.
Infrastructure-only changes under infrastructure/clusters/home can be deployed through a normal push to master
without publishing new application images.
src/main/java/com/thecodinglab/imdbclone Spring Boot backend modules
frontend/src React frontend source
compose.yaml Local Docker Compose services
infrastructure/clusters/home k3s GitOps manifests
infrastructure/movie-seed Movie and media seed pipeline