A full-stack grocery list management application. Users can sign up, manage multiple grocery lists, add items from a catalog, view balance, and see total cost per list.
- Authentication: Sign up and log in with email and password.
- Grocery lists: Create, view, and delete multiple grocery lists.
- List details: Open a list to add or remove items from a catalog of grocery items (with name, description, price, category).
- Balance: View account balance and add money to your balance.
- Cost summary: See the total cost of each list and overall grocery spending.
| Layer | Technologies |
|---|---|
| Backend | Java 21, Spring Boot 3, Spring Security, Spring Data JDBC, PostgreSQL, Caffeine cache |
| Frontend | React 18, Ant Design, Create React App |
| Build | Gradle (monorepo: builds frontend then backend JAR) |
| Deploy | Docker, AWS App Runner, AWS RDS (PostgreSQL), ECR |
GroceryManager/
├── src/main/java/ # Backend (Spring Boot)
├── src/main/resources/ # application.yml, DB init script, and (after build) static frontend
├── web/ # Frontend (React) — source of truth for UI
│ ├── src/
│ └── public/
├── build.gradle # Builds web (npm install + npm run build), syncs to resources/public, then builds JAR
└── Dockerfile # Runs the fat JAR
The Gradle build runs npm install and npm run build in web/, then syncs web/build/ into src/main/resources/public/ so the packaged JAR serves the React app from the same origin as the API.
- Java 21
- Node.js 18+ (for full build and/or frontend dev)
- Docker (for PostgreSQL)
docker-compose up -dThis starts PostgreSQL on port 5433 with database grocerymanager and password secret.
./gradlew clean build -x test
./gradlew bootRunThe app is available at http://localhost:8080. The same server serves the React UI and the API.
Terminal 1 — backend only (no frontend build):
./gradlew bootRun -x syncFrontendTerminal 2 — React dev server (proxies API to 8080):
cd web && npm install && npm startUse http://localhost:3000 for the UI; API calls are proxied to http://localhost:8080 (see web/package.json proxy).
- Create a PostgreSQL instance (e.g. 15.x).
- Note: Endpoint, Port (usually 5432), Database name (
grocerymanager), Master username, Master password. - Ensure the RDS security group allows inbound 5432 from the App Runner service (or the VPC used by App Runner).
In the App Runner service configuration, set:
| Variable | Example / value |
|---|---|
DATABASE_URL |
your-db.xxxx.us-east-2.rds.amazonaws.com |
DATABASE_PORT |
5432 |
DATABASE_USERNAME |
postgres |
DATABASE_PASSWORD |
your RDS master password |
INIT_DB |
always (so schema and seed data run on first start) |
PORT |
8080 |
From the project root (after a full build so the JAR includes the frontend):
./gradlew clean build -x test
docker buildx create --use
docker buildx build --platform=linux/amd64 -t 326803123243.dkr.ecr.us-east-2.amazonaws.com/grocerymanager:latest --load .
aws ecr get-login-password --region us-east-2 | docker login --username AWS --password-stdin 326803123243.dkr.ecr.us-east-2.amazonaws.com
docker push 326803123243.dkr.ecr.us-east-2.amazonaws.com/grocerymanager:latestReplace the ECR URI/region if yours differ.
- Source: ECR image (e.g.
326803123243.dkr.ecr.us-east-2.amazonaws.com/grocerymanager:latest). - Port: 8080.
- Health check: Protocol HTTP, port 8080, path
/or/items. - Add the environment variables from step 2.
After deployment, open the App Runner URL; you get the same UI and API as locally.
Private / educational use as applicable.