Full-stack sample app with:
| Service | Tech | Port (host) |
|---|---|---|
| Frontend | React (Vite build) + nginx | 3000 |
| Backend | Java Spring Boot + JPA | 8000 |
| Database | PostgreSQL 16 | 5432 |
The UI is a small Todo app that creates, lists, toggles, and deletes items in Postgres through the API.
react-java-todo/
├── frontend/ # React (Vite) + nginx
├── backend/ # Spring Boot + Spring Data JPA
├── docker-compose.yml # 3 services: frontend, backend, db
├── k8s/ # Kubernetes Pods/Services/Ingress (not applied by default)
├── .env.example
└── README.md
- How it works (learning guide):
docs/how-it-works.md - Architecture reference:
docs/architecture.md - Kubernetes manifests (optional):
k8s/README.md
From the repo root:
# Docker
docker compose up --build
# or Podman
podman compose up --build
# (or) podman-compose up --buildThen open:
- App UI: http://localhost:3000
- API health: http://localhost:8000/api/health
- Todos API: http://localhost:8000/api/todos
Stop:
docker compose down
# remove DB volume too:
docker compose down -vYou still need PostgreSQL (container or install). Easiest: run only the DB container, then backend + frontend on the host.
docker run --name react-java-todo-db \
-e POSTGRES_USER=todos \
-e POSTGRES_PASSWORD=todos \
-e POSTGRES_DB=todos \
-p 5432:5432 \
-d postgres:16-alpineRequires JDK 21+ and Maven 3.9+.
cd backend
export SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/todos
export SPRING_DATASOURCE_USERNAME=todos
export SPRING_DATASOURCE_PASSWORD=todos
export SERVER_PORT=8000
mvn spring-boot:runAPI: http://localhost:8000/api/health
cd frontend
npm install
npm run devUI: http://localhost:5173
Vite proxies /api → http://localhost:8000.
| Method | Path | Description |
|---|---|---|
| GET | /api/health |
Health + DB ping |
| GET | /api/todos |
List todos |
| POST | /api/todos |
Create {title} |
| PATCH | /api/todos/{id} |
Update todo |
| DELETE | /api/todos/{id} |
Delete todo |
JSON uses snake_case (created_at) so the React client matches the FastAPI demo style.
| Variable | Where | Default |
|---|---|---|
SPRING_DATASOURCE_URL |
backend | jdbc:postgresql://localhost:5432/todos |
SPRING_DATASOURCE_USERNAME |
backend | todos |
SPRING_DATASOURCE_PASSWORD |
backend | todos |
SERVER_PORT |
backend | 8000 |
VITE_API_URL |
frontend | empty (same-origin /api via proxy or nginx) |
See .env.example.
- Compose networking: nginx in the frontend container proxies
/apito thebackendservice; browser only needs port 3000. - Vite is only used at image build time to compile React. At runtime, nginx serves
dist/and proxies API calls (seefrontend/nginx.conf). - Default DB credentials are for demo only — change them before any real deployment.
- Backend auto-creates the
todostable on startup (spring.jpa.hibernate.ddl-auto=update). - Stack is designed for Docker Compose or rootless Podman +
podman compose.