A minimal personal finance tracker with goals, transactions, reports, and saving logs. Built with Node.js, Express, EJS, and PostgreSQL.
- User auth (middleware-protected API routes)
- Transactions: create, update, soft-delete
- Transactions listing with sorting and pagination (page/limit)
- Goals: create, update, soft-delete
- Goal saving logs: view history and add new savings
- Reports: monthly spending summary per user
- EJS views, modular front-end scripts, and shared styles
- Backend: Node.js (ESM), Express
- DB: PostgreSQL (pg)
- Views: EJS
- Front-end: vanilla JS modules, CSS
.
├─ controllers/ # Route handlers (business logic)
│ ├─ accessControllers.js
│ ├─ authControllers.js
│ ├─ goalController.js
│ ├─ goalLogController.js
│ ├─ reportsController.js
│ └─ transactionController.js
├─ middleware/
│ ├─ authMiddleware.js # checks for access token and its validity
│ └─ pageMiddleware.js # checks for refresh token and its validity
├─ models/ # DB access
│ ├─ db.js # pg Pool
│ ├─ goalLogModel.js
│ ├─ goalModel.js
│ ├─ reportsModel.js
│ └─ transactionModel.js
│ └─ userModel.js
├─ public/ # Static assets
│ ├─ js/
│ │ ├─ auth.js
│ │ ├─ goal.js
│ │ ├─ home.js
│ │ ├─ homeEl.js
│ │ ├─ reports.js
│ │ └─ transaction.js
│ │ └─ util.js
│ │ └─ verification.js
│ │ └─ verificationEl.js
│ └─ styles/
│ ├─ base.css
│ ├─ validation.css
│ └─ home.css
├─ routes/
│ ├─ goalRoutes.js
│ ├─ accessRoutes.js
│ ├─ userRoutes.js
│ └─ transactionRoutes.js
├─ views/
│ ├─ home.ejs
│ └─ validation.ejs
├─ schema.sql # DB schema & view
├─ server.js # App entrypoint
├─ package.json
├─ package-lock.json
├─ .gitIgnore
└─ .env
- Node.js 18+
- PostgreSQL 13+
- A
.envfile with DB and JWT configuration
Create .env in project root:
PORT=3000
DB_USER=postgres
DB_PASSWORD=yourpassword
DB_HOST=localhost
DB_PORT=5432
DB_NAME=expense_tracker
JWT_SECRET=replace-with-strong-secret
- Create database:
createdb expense_tracker
- Apply schema:
psql -U postgres -d expense_tracker -f schema.sql
This creates:
users,transactions,goals,goal_saving_logtablesmonthly_summaryview for reports
Install dependencies:
npm installTo Start run :
npm startOpen in browser:
http://localhost:PORT (Insert the port number here)
-
Transactions:
GET /api/transactions?sortBy=created_at|transaction_name|transaction_amount&sortOrder=ASC|DESC&page=1&limit=10&filterByName=- Response:
{ data: [...], page, limit, hasMore }
- Response:
POST /api/transactionsbody:{ name, amount, detail? }PUT /api/transactions/:idbody:{ name, amount, detail? }DELETE /api/transactions/:id
-
Goals:
-
GET /api/goals -
POST /api/goalsbody:{ name, totalAmount, freq, goalDeadline } -
PUT /api/goals/:id -
DELETE /api/goals/:id -
Goal Logs:
GET /api/goals/goalLog/:goalIdPOST /api/goals/goalLogbody:{ goalId,amount, note? }
-
Reports:
GET /api/goals/reports/monthly-summary- Response:
{ data: [{ year, month, total_spent }, ...] }
- Response:
-
All /api/* routes are protected by authMiddleware, which should set req.user = { id, ... }.
views/home.ejsloads/js/home.jsas module.public/js/home.jsgenerates/retrieves an access token and calls:allEvents()fromhomeEl.js
homeEl.jswires tab switching and calls:goalEvents()transactionEvents()reportsEvents()
MIT