Skip to content

Elegant Budget Tracker is a MERN stack app for tracking income and expenses with a clean React + TypeScript UI. It features JWT auth, secure cookies, AWS deployment (S3 + EC2), and cost-saving strategies. Built as part of an AWS internship project, it’s ideal for learning full-stack and cloud development.

License

Notifications You must be signed in to change notification settings

rohitTo95/elegant-budget-tracker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

75 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ’° Elegant Budget Tracker

Screenshot From 2025-07-12 00-54-14
TypeScript React Node.js Express.js MongoDB Tailwind CSS Nginx AWS

A modern, production-ready budget tracking application built with TypeScript

Track your income and expenses with enterprise-grade architecture and security


🌟 Features

  • ✨ Modern UI: Beautiful, responsive design with Tailwind CSS and Radix UI components
  • πŸ” Secure Authentication: JWT-based authentication with localStorage token storage (no CORS issues)
  • πŸ“Š Transaction Management: Full CRUD operations for financial transactions
  • πŸ“ˆ Visual Analytics: Interactive charts and comprehensive financial summaries
  • πŸ—οΈ Type-Safe: Built entirely with TypeScript for better developer experience
  • πŸš€ Production Ready: Enterprise-grade deployment with nginx reverse proxy
  • πŸ“± Mobile Responsive: Progressive Web App design for all device sizes
  • 🌐 Cross-Origin Optimized: localStorage-based auth eliminates cookie CORS issues
  • ⚑ High Performance: nginx load balancing and optimized API endpoints
  • πŸ”’ Security Focused: JWT tokens, password hashing, and secure headers
  • πŸ“¦ CI/CD Pipeline: Automated testing and deployment workflows

πŸ—οΈ Architecture

Development Environment

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                 β”‚    β”‚                 β”‚    β”‚                 β”‚
β”‚   React Frontend│◄────   Express API   │◄────   MongoDB       β”‚
β”‚   (Vite + TS)   β”‚    β”‚   (Node.js)     β”‚    β”‚   Database      β”‚
β”‚   localhost:3000β”‚    β”‚  localhost:5000 β”‚    β”‚   Port 27017    β”‚
β”‚                 β”‚    β”‚                 β”‚    β”‚                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Production Environment (AWS)

    Internet
        β”‚
        β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   AWS S3 Bucket β”‚  ◄── Static Frontend Hosting
β”‚   React Build   β”‚      (expencetracker9993)
β”‚                 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚ HTTPS/HTTP Requests
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   AWS EC2       β”‚  ◄── Backend Server (13.204.100.131)
β”‚   Ubuntu Server β”‚
β”‚                 β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚   nginx     β”‚β”‚  ◄── Reverse Proxy & Load Balancer
β”‚  β”‚   Port 80   β”‚β”‚      CORS Handler & Static Assets
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜β”‚
β”‚         β”‚       β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”β”‚
β”‚  β”‚  Node.js    β”‚β”‚  ◄── Express API Server
β”‚  β”‚  Port 5000  β”‚β”‚      JWT Authentication
β”‚  β”‚  PM2 Managedβ”‚β”‚      Business Logic
β”‚  β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”˜
          β”‚
          β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   MongoDB       β”‚  ◄── Database Server
β”‚   Atlas/Local   β”‚      User Data & Transactions
β”‚   Port 27017    β”‚      Mongoose ODM
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Authentication Flow (localStorage-based)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             β”‚    β”‚             β”‚    β”‚             β”‚    β”‚             β”‚
β”‚  S3 Frontend│───▢│   nginx     │───▢│ Express API │───▢│  MongoDB    β”‚
β”‚             β”‚    β”‚ (Port 80)   β”‚    β”‚(Port 5000)  β”‚    β”‚             β”‚
β”‚             β”‚    β”‚             β”‚    β”‚             β”‚    β”‚             β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                                     β”‚
       β”‚ 1. Login Request                    β”‚ 2. JWT Token Response
       β”‚ (email/password)                    β”‚ (stored in localStorage)
       β”‚                                     β”‚
       β”‚ 3. Subsequent Requests              β”‚
       β”‚ Authorization: Bearer <token>       β”‚
       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

πŸ“ Project Structure

elegant-budget-tracker/
β”œβ”€β”€ πŸ“ Backend/                 # Node.js Express API
β”‚   β”œβ”€β”€ πŸ“ src/
β”‚   β”‚   β”œβ”€β”€ πŸ“ api/             # Business logic
β”‚   β”‚   β”‚   β”œβ”€β”€ user.ts         # User authentication logic
β”‚   β”‚   β”‚   └── transaction.ts  # Transaction CRUD operations
β”‚   β”‚   β”œβ”€β”€ πŸ“ database/        # Database configuration
β”‚   β”‚   β”‚   β”œβ”€β”€ db_connect.ts   # MongoDB connection
β”‚   β”‚   β”‚   └── πŸ“ models/      # Mongoose schemas
β”‚   β”‚   β”‚       β”œβ”€β”€ user.ts     # User model
β”‚   β”‚   β”‚       └── transactions.ts # Transaction model
β”‚   β”‚   β”œβ”€β”€ πŸ“ middleware/      # Express middleware
β”‚   β”‚   β”‚   └── πŸ“ jwt/         # JWT authentication
β”‚   β”‚   β”‚       └── authenticateToken.ts # Token verification
β”‚   β”‚   β”œβ”€β”€ πŸ“ routes/          # Route handlers (unused in current setup)
β”‚   β”‚   β”‚   β”œβ”€β”€ auth.ts         # Authentication routes
β”‚   β”‚   β”‚   └── transactions.ts # Transaction routes
β”‚   β”‚   └── πŸ“ types/           # TypeScript definitions
β”‚   β”‚       └── express.d.ts    # Express type extensions
β”‚   β”œβ”€β”€ server.ts               # Main server file with all routes
β”‚   β”œβ”€β”€ ecosystem.config.js     # PM2 process manager configuration
β”‚   β”œβ”€β”€ package.json            # Dependencies and scripts
β”‚   └── tsconfig.json           # TypeScript configuration
β”‚
β”œβ”€β”€ πŸ“ Frontend/                # React Vite application
β”‚   β”œβ”€β”€ πŸ“ src/
β”‚   β”‚   β”œβ”€β”€ πŸ“ components/      # React components
β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ Dashboard/   # Dashboard-specific components
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ BalanceSummary.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ExpensePieChart.tsx
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ NewTransactionForm.tsx
β”‚   β”‚   β”‚   β”‚   └── TransactionHistory.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ πŸ“ ui/          # Reusable UI components (Radix)
β”‚   β”‚   β”‚   β”œβ”€β”€ ErrorBoundary.tsx
β”‚   β”‚   β”‚   └── ProtectedRoute.tsx
β”‚   β”‚   β”œβ”€β”€ πŸ“ context/         # React Context providers
β”‚   β”‚   β”‚   β”œβ”€β”€ AuthContext.tsx # localStorage-based auth context
β”‚   β”‚   β”‚   β”œβ”€β”€ ToastContext.tsx# Toast notifications
β”‚   β”‚   β”‚   └── TransactionContext.tsx # Transaction state
β”‚   β”‚   β”œβ”€β”€ πŸ“ hooks/           # Custom React hooks
β”‚   β”‚   β”‚   β”œβ”€β”€ use-logout.ts   # Enhanced logout with localStorage
β”‚   β”‚   β”‚   β”œβ”€β”€ use-mobile.tsx  # Mobile detection hook
β”‚   β”‚   β”‚   └── use-toast.ts    # Toast hook
β”‚   β”‚   β”œβ”€β”€ πŸ“ lib/             # Utility libraries
β”‚   β”‚   β”‚   β”œβ”€β”€ axios.ts        # Axios config with Bearer token
β”‚   β”‚   β”‚   └── utils.ts        # Utility functions
β”‚   β”‚   β”œβ”€β”€ πŸ“ pages/           # Page components
β”‚   β”‚   β”‚   β”œβ”€β”€ Dashboard.tsx   # Main dashboard
β”‚   β”‚   β”‚   β”œβ”€β”€ Index.tsx       # Landing page
β”‚   β”‚   β”‚   β”œβ”€β”€ Login.tsx       # Login page
β”‚   β”‚   β”‚   β”œβ”€β”€ SignUp.tsx      # Registration page
β”‚   β”‚   β”‚   └── NotFound.tsx    # 404 page
β”‚   β”‚   └── πŸ“ types/           # TypeScript definitions
β”‚   β”‚       └── index.ts        # Type definitions
β”‚   β”œβ”€β”€ πŸ“ public/
β”‚   β”‚   β”œβ”€β”€ _redirects          # S3/Netlify routing configuration
β”‚   β”‚   β”œβ”€β”€ favicon.ico
β”‚   β”‚   β”œβ”€β”€ placeholder.svg
β”‚   β”‚   └── robots.txt
β”‚   β”œβ”€β”€ vite.config.ts          # Vite configuration
β”‚   β”œβ”€β”€ tailwind.config.ts      # Tailwind CSS configuration
β”‚   β”œβ”€β”€ components.json         # Shadcn/ui configuration
β”‚   └── package.json            # Dependencies and scripts
β”‚
β”œβ”€β”€ nginx-expense-tracker.conf  # nginx reverse proxy configuration
└── README.md                   # This file

πŸš€ Quick Start

Prerequisites

Make sure you have the following installed:

1. Clone the Repository

git clone https://github.com/rohitTo95/elegant-budget-tracker.git
cd elegant-budget-tracker

2. Backend Setup

# Navigate to backend directory
cd Backend

# Install dependencies
npm install

# Create environment file (create .env based on your needs)
touch .env

# Add the following to .env file:
# MONGODB_URI=mongodb://localhost:27017/budget-tracker
# JWT_SECRET=your-super-secret-jwt-key-here
# PORT=5000
# NODE_ENV=development
# FRONTEND_URL=http://localhost:3000

3. Frontend Setup

# Navigate to frontend directory (from project root)
cd Frontend

# Install dependencies
npm install

# Create environment file (create .env based on your needs)
touch .env

# Add the following to .env file:
# VITE_BACKEND_URL=http://localhost:5000

4. Start the Application

# Terminal 1 - Start Backend
cd Backend
npm run dev:server

# Terminal 2 - Start Frontend
cd Frontend
npm run dev

5. Access the Application

πŸ”§ Environment Variables

Backend (.env)

# Database Configuration
MONGODB_URI=mongodb://localhost:27017/budget-tracker

# JWT Authentication
JWT_SECRET=your-super-secret-jwt-key-here

# Server Configuration
PORT=5000
NODE_ENV=development

# CORS Configuration
FRONTEND_URL=http://localhost:3000

Backend Production (.env.production)

# Database Configuration
MONGODB_URI=mongodb://your-production-mongodb-uri

# JWT Authentication
JWT_SECRET=your-production-jwt-secret

# Server Configuration
PORT=5000
NODE_ENV=production

# CORS Configuration (AWS S3 Frontend)
FRONTEND_URL=http://expencetracker9993.s3-website.ap-south-1.amazonaws.com

Frontend (.env)

# API Configuration (Development)
VITE_BACKEND_URL=http://localhost:5000

Frontend Production (.env.production)

# API Configuration (Production via nginx)
VITE_BACKEND_URL=http://13.204.100.131

πŸ“‘ API Endpoints & Usage

Base URL

  • Development: http://localhost:5000
  • Production: http://13.204.100.131

Content Type

All API requests should include:

Content-Type: application/json

Authentication

Protected endpoints require JWT token in header:

Authorization: Bearer <your-jwt-token>

πŸ” Authentication Endpoints

1. Root Endpoint

GET /

Check if the API server is running.

curl -X GET http://localhost:5000/

Response:

API SERVER IS READY!

2. User Registration (Signup)

POST /api/auth/signup

Register a new user account.

Request Body:

{
  "name": "string (required)",
  "email": "string (required, valid email)",
  "password": "string (required)"
}

Example:

curl -X POST http://localhost:5000/api/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "john.doe@example.com",
    "password": "SecurePassword123"
  }'

Success Response (201):

{
  "message": "User created successfully",
  "success": true
}

Error Response (400):

{
  "message": "User with this email already exists",
  "error": "USER_EXISTS"
}

3. User Login

POST /api/auth/login

Authenticate user and receive JWT token.

Request Body:

{
  "email": "string (required)",
  "password": "string (required)"
}

Example:

curl -X POST http://localhost:5000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "john.doe@example.com",
    "password": "SecurePassword123"
  }'

Success Response (200):

{
  "message": "Login successful",
  "user": {
    "id": "65f8b4c4d9e7f8a9b0c1d2e3",
    "name": "John Doe",
    "email": "john.doe@example.com",
    "createdAt": "2024-01-15T10:30:00.000Z",
    "updatedAt": "2024-01-15T10:30:00.000Z"
  },
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

Error Response (401):

{
  "message": "Invalid credentials",
  "error": "INVALID_CREDENTIALS"
}

4. Check Authentication Status

GET /api/auth/check

Verify if the current JWT token is valid.

Headers Required:

Authorization: Bearer <your-jwt-token>

Example:

curl -X GET http://localhost:5000/api/auth/check \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Success Response (200):

{
  "success": true,
  "user": {
    "id": "65f8b4c4d9e7f8a9b0c1d2e3",
    "name": "John Doe",
    "email": "john.doe@example.com"
  }
}

Error Response (401):

{
  "success": false,
  "message": "Not authenticated"
}

5. User Logout

POST /api/auth/logout

Logout user (frontend should clear localStorage token).

Example:

curl -X POST http://localhost:5000/api/auth/logout

Success Response (200):

{
  "success": true,
  "message": "Logged out successfully"
}

πŸ’° Transaction Endpoints

1. Create Transaction

POST /api/transaction/create

Create a new income or expense transaction.

Headers Required:

Authorization: Bearer <your-jwt-token>
Content-Type: application/json

Request Body:

{
  "type": "string (required: 'income' or 'expense')",
  "amount": "number (required, positive)",
  "category": "string (required)",
  "description": "string (required)",
  "date": "string (required, valid date format)"
}

Example - Income Transaction:

curl -X POST http://localhost:5000/api/transaction/create \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -d '{
    "type": "income",
    "amount": 5000,
    "category": "Salary",
    "description": "Monthly salary payment",
    "date": "2024-01-15"
  }'

Example - Expense Transaction:

curl -X POST http://localhost:5000/api/transaction/create \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -d '{
    "type": "expense",
    "amount": 1200,
    "category": "Groceries",
    "description": "Weekly grocery shopping",
    "date": "2024-01-16"
  }'

Success Response (201):

{
  "message": "Transaction created successfully",
  "success": true
}

Error Response (400) - Missing Fields:

{
  "message": "All fields (userId, amount, description, category, type, date) are required",
  "error": "MISSING_FIELDS"
}

Error Response (400) - Invalid Amount:

{
  "message": "Amount must be a valid number",
  "error": "INVALID_AMOUNT"
}

Error Response (400) - Invalid Type:

{
  "message": "Type must be either \"income\" or \"expense\"",
  "error": "INVALID_TYPE"
}

Error Response (400) - Invalid Date:

{
  "message": "Date must be in a valid format",
  "error": "INVALID_DATE"
}

2. Get All Transactions

GET /api/transactions

Retrieve all transactions for the authenticated user.

Headers Required:

Authorization: Bearer <your-jwt-token>

Example:

curl -X GET http://localhost:5000/api/transactions \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Success Response (200):

{
  "message": "Transactions retrieved successfully",
  "success": true,
  "transactions": [
    {
      "id": "65f8b5c4d9e7f8a9b0c1d2e4",
      "type": "income",
      "amount": 5000,
      "category": "Salary",
      "description": "Monthly salary payment",
      "date": "2024-01-15T00:00:00.000Z",
      "userId": "65f8b4c4d9e7f8a9b0c1d2e3",
      "createdAt": "2024-01-15T10:35:00.000Z",
      "updatedAt": "2024-01-15T10:35:00.000Z"
    },
    {
      "id": "65f8b5c4d9e7f8a9b0c1d2e5",
      "type": "expense",
      "amount": 1200,
      "category": "Groceries",
      "description": "Weekly grocery shopping",
      "date": "2024-01-16T00:00:00.000Z",
      "userId": "65f8b4c4d9e7f8a9b0c1d2e3",
      "createdAt": "2024-01-15T10:40:00.000Z",
      "updatedAt": "2024-01-15T10:40:00.000Z"
    }
  ]
}

Error Response (401):

{
  "message": "User authentication failed",
  "error": "USER_NOT_AUTHENTICATED"
}

3. Update Transaction

PUT /api/transaction/:id

Update an existing transaction by ID.

Headers Required:

Authorization: Bearer <your-jwt-token>
Content-Type: application/json

Path Parameters:

  • id - Transaction ID (required)

Request Body (all fields optional):

{
  "type": "string (optional: 'income' or 'expense')",
  "amount": "number (optional)",
  "category": "string (optional)",
  "description": "string (optional)",
  "date": "string (optional, valid date format)"
}

Example:

curl -X PUT http://localhost:5000/api/transaction/65f8b5c4d9e7f8a9b0c1d2e4 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -d '{
    "amount": 5500,
    "description": "Monthly salary payment - updated amount"
  }'

Success Response (200):

{
  "message": "Transaction updated successfully",
  "success": true,
  "transaction": {
    "id": "65f8b5c4d9e7f8a9b0c1d2e4",
    "type": "income",
    "amount": 5500,
    "category": "Salary",
    "description": "Monthly salary payment - updated amount",
    "date": "2024-01-15T00:00:00.000Z",
    "userId": "65f8b4c4d9e7f8a9b0c1d2e3",
    "createdAt": "2024-01-15T10:35:00.000Z",
    "updatedAt": "2024-01-15T11:00:00.000Z"
  }
}

Error Response (400) - Transaction Not Found:

{
  "message": "Transaction not found or access denied",
  "error": "TRANSACTION_NOT_FOUND"
}

Error Response (401):

{
  "message": "User authentication failed",
  "error": "USER_NOT_AUTHENTICATED"
}

4. Delete Transaction

DELETE /api/transaction/:id

Delete a transaction by ID.

Headers Required:

Authorization: Bearer <your-jwt-token>

Path Parameters:

  • id - Transaction ID (required)

Example:

curl -X DELETE http://localhost:5000/api/transaction/65f8b5c4d9e7f8a9b0c1d2e4 \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."

Success Response (200):

{
  "message": "Transaction deleted successfully",
  "success": true
}

Error Response (400) - Transaction Not Found:

{
  "message": "Transaction not found or access denied",
  "error": "TRANSACTION_NOT_FOUND"
}

Error Response (401):

{
  "message": "User authentication failed",
  "error": "USER_NOT_AUTHENTICATED"
}

πŸ§ͺ Testing API Endpoints

Automated Testing Script

We've provided a comprehensive testing script that tests all API endpoints with proper error handling and colored output. The script is located at test-api-endpoints.sh in the project root.

To run the automated tests:

# Make sure your backend server is running
cd Backend
npm run dev

# In another terminal, run the test script
cd /path/to/elegant-budget-tracker
chmod +x test-api-endpoints.sh
./test-api-endpoints.sh

The script will:

  • βœ… Test all 9 API endpoints
  • βœ… Handle authentication flow automatically
  • βœ… Test error scenarios and edge cases
  • βœ… Provide colored output for easy reading
  • βœ… Generate detailed test results summary
  • βœ… Work without external dependencies (no jq required)

Manual Testing Examples

For manual testing or integration with other tools, here are individual curl commands:

Authentication Flow Test

BASE_URL="http://localhost:5000"

# 1. Test server status
curl -X GET $BASE_URL/

# 2. Register new user
curl -X POST $BASE_URL/api/auth/signup \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Test User",
    "email": "test@example.com",
    "password": "TestPassword123"
  }'

# 3. Login and get token
curl -X POST $BASE_URL/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "test@example.com",
    "password": "TestPassword123"
  }'

# Extract token and use it in subsequent requests
TOKEN="your_jwt_token_here"

# 4. Check authentication
curl -X GET $BASE_URL/api/auth/check \
  -H "Authorization: Bearer $TOKEN"

# 5. Create income transaction
curl -X POST $BASE_URL/api/transaction/create \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "type": "income",
    "amount": 5000,
    "category": "Salary",
    "description": "Monthly salary",
    "date": "2024-01-15"
  }'

# 6. Get all transactions
curl -X GET $BASE_URL/api/transactions \
  -H "Authorization: Bearer $TOKEN"

# 7. Test logout
curl -X POST $BASE_URL/api/auth/logout

Error Testing Examples

# Test missing authentication
curl -X GET http://localhost:5000/api/transactions

# Test invalid credentials
curl -X POST http://localhost:5000/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "wrong@example.com",
    "password": "wrongpassword"
  }'

# Test invalid transaction data
curl -X POST http://localhost:5000/api/transaction/create \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -d '{
    "type": "invalid_type",
    "amount": "not_a_number",
    "category": "",
    "description": "",
    "date": "invalid_date"
  }'

🌐 Current Deployment

Production URLs

Production Testing

# Test production API
curl -X GET http://13.204.100.131/

# Test CORS configuration
curl -H "Origin: http://expencetracker9993.s3-website.ap-south-1.amazonaws.com" \
     -H "Access-Control-Request-Method: POST" \
     -H "Access-Control-Request-Headers: Content-Type,Authorization" \
     -X OPTIONS http://13.204.100.131/api/auth/login

πŸ› οΈ Built With

Backend Technologies

  • Node.js - JavaScript runtime for server-side development
  • Express.js - Minimal and flexible web application framework
  • TypeScript - Type safety for backend development
  • MongoDB - NoSQL document database
  • Mongoose - MongoDB ODM with schema validation
  • JWT (jsonwebtoken) - Stateless authentication tokens
  • bcrypt - Password hashing for security
  • CORS - Cross-origin resource sharing middleware

Frontend Technologies

  • React 18 - Modern UI library with hooks and context
  • TypeScript - Type safety and better developer experience
  • Vite - Fast build tool and development server
  • Tailwind CSS - Utility-first CSS framework
  • Radix UI - Accessible headless UI components
  • React Hook Form - Performant form management
  • Recharts - Responsive chart library for data visualization
  • Axios - HTTP client with interceptors for JWT authentication
  • React Router - Client-side routing with protected routes

DevOps & Infrastructure

  • nginx - High-performance reverse proxy and load balancer
  • PM2 - Advanced production process manager for Node.js
  • AWS S3 - Static website hosting for frontend
  • AWS EC2 - Virtual server for backend hosting

🚒 Deployment

nginx Configuration

server {
    listen 80;
    server_name 13.204.100.131;

    location /api {
        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }

    location / {
        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

PM2 Deployment

# Start the application
cd Backend
pm2 start ecosystem.config.js --env production

# Monitor the application
pm2 logs
pm2 status

🚨 Troubleshooting

Common API Errors

Status Code Error Description Solution
400 MISSING_FIELDS Required fields not provided Check request body contains all required fields
400 INVALID_AMOUNT Amount is not a valid number Ensure amount is a positive number
400 INVALID_TYPE Transaction type invalid Use only 'income' or 'expense'
400 INVALID_DATE Date format invalid Use valid date format (YYYY-MM-DD)
401 USER_NOT_AUTHENTICATED Missing or invalid JWT token Include valid Authorization header
401 INVALID_CREDENTIALS Wrong email/password Check login credentials
404 TRANSACTION_NOT_FOUND Transaction doesn't exist Verify transaction ID and ownership
500 SERVER_ERROR Internal server error Check server logs and database connection

Debug Commands

# Check backend logs
pm2 logs

# Test database connection
mongo mongodb://localhost:27017/budget-tracker

# Check if backend is running
curl -X GET http://localhost:5000/

# Verify JWT token (decode)
# Use jwt.io to decode and verify token structure

πŸ“ License

This project is licensed under the MIT License.

πŸ‘¨β€πŸ’» Author

Rohit - GitHub Profile


⭐ Star this repository if you find it helpful!

πŸš€ Deployed on AWS with enterprise-grade architecture

Made with ❀️ by Rohit

About

Elegant Budget Tracker is a MERN stack app for tracking income and expenses with a clean React + TypeScript UI. It features JWT auth, secure cookies, AWS deployment (S3 + EC2), and cost-saving strategies. Built as part of an AWS internship project, it’s ideal for learning full-stack and cloud development.

Resources

License

Stars

Watchers

Forks

Languages