Spendly is a personal expense-tracking product that helps you record, organize, and query your spending by category and date. It exposes a REST API for users and expenses, with a React web client for the interface.
- User accounts — Sign up and log in to manage your own expenses
- Expense tracking — Create, update, and delete expenses with amount, description, category, and date
- Filtering — List expenses by user, category, or date range
- REST API — Backend built with Spring Boot; integrate from any client (web, mobile, or scripts)
| Layer | Stack |
|---|---|
| Backend | Java, Spring Boot, JPA |
| Database | PostgreSQL |
| Frontend | React, TypeScript, Vite |
Base URL (default): http://localhost:8080
All expense amounts use decimal precision (e.g. 19.99). Dates use ISO 8601 format: YYYY-MM-DD.
Base path: /users
| Method | Endpoint | Description |
|---|---|---|
| GET | /users/ping |
Health check; returns "hello" |
| POST | /users/signup |
Create a new user |
| GET | /users/login/{id} |
Get user by ID (login) |
Request
POST /users/signup
Content-Type: application/json{
"name": "Jane Doe",
"email": "jane@example.com"
}Response — User object with id, name, email.
Request
GET /users/login/{id}Response — User object.
Base path: /expenses
| Method | Endpoint | Description |
|---|---|---|
| POST | /expenses/create |
Create an expense |
| GET | /expenses/{id} |
Get expense by ID |
| GET | /expenses/user/{userId} |
List all expenses for a user |
| GET | /expenses/user/{userId}/category?category=... |
List by user and category |
| GET | /expenses/user/{userId}/range?start=...&end=... |
List by user and date range |
| PUT | /expenses/{id} |
Update an expense |
| DELETE | /expenses/{id} |
Delete an expense |
Request
POST /expenses/create
Content-Type: application/json{
"amount": 49.99,
"description": "Weekly groceries",
"category": "Food",
"expenseDate": "2025-02-08",
"userId": 1
}Validation
amount— Required, must be ≥ 0description— Required, non-blankcategory— Required, non-blankexpenseDate— Required, ISO dateuserId— Required
Response — Full expense object including generated id.
Request
GET /expenses/{id}Response — Single expense.
Request
GET /expenses/user/{userId}Response — Array of expenses for that user.
Request
GET /expenses/user/{userId}/category?category=FoodResponse — Array of expenses for that user in the given category.
Request
GET /expenses/user/{userId}/range?start=2025-02-01&end=2025-02-28Query params: start and end in YYYY-MM-DD.
Response — Array of expenses within the date range.
Request
PUT /expenses/{id}
Content-Type: application/jsonBody: same shape as create (amount, description, category, expenseDate, userId).
Response — Updated expense.
Request
DELETE /expenses/{id}Response — 204 No Content.
| Field | Type | Notes |
|---|---|---|
| id | number | Auto-generated |
| name | string | Required |
| string | Required, unique |
| Field | Type | Notes |
|---|---|---|
| id | number | Auto-generated |
| amount | number | ≥ 0, decimal |
| description | string | Required |
| category | string | Required |
| expenseDate | string | ISO date |
| user | User | Owner of expense |
- Java 17+
- Node.js 18+
- PostgreSQL (default config:
mydb, userpostgres, passwordpostgres, port5432)
cd server
./mvnw spring-boot:runAPI is available at http://localhost:8080. Configure database in server/src/main/resources/application.properties if needed.
cd client
npm install
npm run devOpen the URL shown in the terminal (e.g. http://localhost:5173).
spendly/
├── client/ # React + Vite frontend
├── server/ # Spring Boot API
│ └── src/main/java/com/jsndz/spendly/
│ ├── controller/ # REST endpoints
│ ├── dto/ # Request DTOs
│ ├── model/ # JPA entities
│ ├── repository/ # Data access
│ └── service/ # Business logic
└── README.md
See repository license if applicable.