A powerful and intuitive personal finance application designed to help you take control of your money. Track your income and expenses, set personalized budgets, generate reports, and scan receipts with OCR technology.
- Transaction Management: Add, edit, delete, and view income and expense transactions
- Category Management: Organize transactions into categories with budget limits
- Receipt Scanning: OCR-powered receipt scanning using Tesseract (Indonesian language support)
- Financial Reports: Generate detailed reports with charts and visualizations
- Data Export: Export financial data to CSV and PDF formats
- Multi-Currency Support: Track transactions in different currencies with automatic conversion
- Dashboard: Real-time summary of your financial status
- User registration and login with JWT authentication
- Password hashing with bcrypt
- Admin features for user management
- Protected API routes with middleware
- Frontend: Next.js 15 (App Router), React 18, TypeScript, Tailwind CSS
- UI Components: shadcn/ui (Radix UI)
- Database: PostgreSQL with Prisma ORM
- Authentication: NextAuth.js with JWT
- Charts: Recharts
- Receipt OCR: Python FastAPI service with Tesseract OCR
- AI Integration: Genkit with Google AI
- PDF Generation: jsPDF with autoTable
- Image Processing: html2canvas, Tesseract.js (client-side OCR)
penny-pincher/
├── prisma/
│ ├── schema.prisma # Database schema
│ └── migrations/ # Database migrations
├── receipt-scan/ # Python OCR service
│ ├── app.py # FastAPI application
│ ├── utils/ # OCR utilities
│ ├── requirements.txt # Python dependencies
│ └── README.md # Receipt service documentation
├── scripts/
│ ├── run-migrations.sh # Migration runner script
│ └── seed-admin.ts # Admin user seeder
├── src/
│ ├── app/ # Next.js App Router pages
│ │ ├── api/ # API routes (App Router)
│ │ │ ├── auth/[...nextauth]/ # NextAuth routes
│ │ │ └── process/receipts/scan/ # Receipt scanning API
│ │ ├── categories/ # Categories page
│ │ ├── login/ # Login page
│ │ ├── reports/ # Reports page
│ │ ├── scanReceipts/ # Receipt scanner page
│ │ ├── transactions/ # Transactions page
│ │ └── users/ # User management page
│ ├── components/ # React components
│ │ ├── categories/ # Category components
│ │ ├── dashboard/ # Dashboard widgets
│ │ ├── layout/ # Layout components
│ │ ├── reports/ # Report components
│ │ ├── transactions/ # Transaction components
│ │ └── ui/ # shadcn/ui components
│ ├── contexts/ # React Context providers
│ │ ├── AuthContext.tsx # Authentication state
│ │ ├── CurrencyContext.tsx # Currency settings
│ │ └── ThemeContext.tsx # Theme settings
│ ├── hooks/ # Custom React hooks
│ │ ├── useAuth.ts # Authentication hook
│ │ ├── useCategories.ts # Categories hook
│ │ ├── useCurrency.ts # Currency hook
│ │ ├── useTheme.ts # Theme hook
│ │ └── useTransactions.ts # Transactions hook
│ ├── lib/ # Utility libraries
│ │ ├── authOptions.ts # NextAuth configuration
│ │ ├── constants.ts # App constants
│ │ ├── env.ts # Environment variables
│ │ ├── logger.ts # Logging utility
│ │ ├── prisma.ts # Prisma client
│ │ ├── types.ts # TypeScript types
│ │ ├── utils.ts # Utility functions
│ │ └── validators.ts # Zod validators
│ ├── middleware/ # Next.js middleware
│ │ └── authMiddleware.ts # Authentication middleware
│ └── pages/ # Legacy Next.js pages
│ └── api/ # Legacy API routes
│ ├── auth/ # Authentication endpoints
│ └── process/ # Transaction/Category endpoints
├── public/ # Static assets
├── docker-compose.yaml # Production Docker configuration
├── dev-compose.yaml # Development Docker configuration
├── Dockerfile # Container build file
└── package.json # NPM dependencies
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/auth/register |
Register new user |
| POST | /api/auth/login |
Login user |
| POST | /api/auth/logout |
Logout user |
| DELETE | /api/auth/delete |
Delete user account |
| PUT | /api/auth/update |
Update user password |
| GET | /api/auth/user |
Get current user |
| GET | /api/auth/users |
List all users (admin) |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/process/transactions |
List user transactions |
| POST | /api/process/transactions |
Create transaction |
| GET | /api/process/transactions/:id |
Get transaction |
| PUT | /api/process/transactions/:id |
Update transaction |
| DELETE | /api/process/transactions/:id |
Delete transaction |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/process/categories |
List user categories |
| POST | /api/process/categories |
Create category |
| GET | /api/process/categories/:id |
Get category |
| PUT | /api/process/categories/:id |
Update category |
| DELETE | /api/process/categories/:id |
Delete category |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/process/receipts/scan |
Scan receipt image |
id: Auto-increment IDusername: Unique usernamepassword: Hashed passwordisAdmin: Admin flagcreatedAt,updatedAt: Timestamps
id: Auto-increment IDtype: "income" or "expense"amount: Transaction amountcategoryId: Associated categoryuserId: Associated userdate: Transaction datenotes: Optional notesreceiptImage: Receipt image pathreceiptData: OCR extracted data (JSON)scannedFromReceipt: Boolean flagcreatedAt,updatedAt: Timestamps
id: Auto-increment IDname: Category namebudget: Optional budget limitisDefault: Default category flaguserId: Associated usercreatedAt,updatedAt: Timestamps
┌─────────────────┐ ┌─────────────────┐
│ User │ │ Category │
├─────────────────┤ ├─────────────────┤
│ id (PK) │ │ id (PK) │
│ username │ │ name │
│ password │ │ budget │
│ isAdmin │ 1 │ isDefault │
│ createdAt ├────────►│ userId (FK) │
│ updatedAt │ N │ createdAt │
└─────────────────┘ │ updatedAt │
│ └─────────────────┘
│ 1
│
▼ N
┌─────────────────┐ ┌─────────────────┐
│ Transaction │ N │ Category │
├─────────────────┤◄────────│ │
│ id (PK) │ 1 │ │
│ type │ │ │
│ amount │ │ │
│ categoryId (FK) │ │ │
│ userId (FK) │ │ │
│ date │ │ │
│ notes │ │ │
│ receiptImage │ │ │
│ receiptData │ │ │
│ scannedFromReceipt │ │
│ createdAt │ │ │
│ updatedAt │ │ │
└─────────────────┘ └─────────────────┘
Relationships:
- User → Transaction: One-to-Many (1:N)
- User → Category: One-to-Many (1:N)
- Transaction → Category: Many-to-One (N:1)
- Node.js 20+
- PostgreSQL
- Docker (optional, for containerized setup)
-
Clone the repository:
git clone https://github.com/sdkdev15/penny-pincher.git cd penny-pincher -
Install dependencies:
npm install
-
Set up environment variables: Create a
.envfile in the root directory:DATABASE_URL=postgresql://user:password@localhost:5432/penny_pincher JWT_SECRET=your-super-secret-jwt-key JWT_EXPIRES_IN=1d -
Set up the database:
npm run build
Or run migrations manually:
npx prisma migrate dev
-
Run the application:
npm run dev
The app will be available at http://localhost:9003
Development:
docker-compose -f dev-compose.yaml up -dProduction:
docker-compose up -dRun migration:
docker-compose exec -T nodeapp npx prisma migrate deploySeed Data:
-
Seed Admin User (wajib pertama kali):
docker cp scripts/seed-admin.ts penny:/app/scripts/seed-admin.ts docker exec penny npx tsx /app/scripts/seed-admin.ts -
Seed Default Categories (setelah admin dibuat):
docker cp scripts/seed-categories.ts penny:/app/scripts/seed-categories.ts docker exec penny npx tsx /app/scripts/seed-categories.tsDefault categories (13 categories):
Kategori Budget Salary - Food & Groceries 3,000,000 Rent/Mortgage - Utilities 150,000 Transportation 400,000 Entertainment 500,000 Healthcare - Education - Shopping 350,000 Gifts/Donations - Freelance Income - Investments - Miscellaneous -
The receipt scanning feature uses a separate Python FastAPI service:
- Health Check:
GET http://localhost:8000/health - Scan Receipt:
POST http://localhost:8000/scan - Indonesian Language Support: Tesseract OCR with
indandengmodels
The service extracts:
- Store name
- Date
- Line items
- Total amount
- Raw text
See receipt-scan/README.md for detailed documentation.
npm run dev # Start development server (port 9003)
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLint
npm run typecheck # Run TypeScript checknpx tsx scripts/seed-admin.ts- Fork the repository
- Create your feature branch:
git checkout -b feature-name - Commit your changes:
git commit -m "Add feature-name" - Push to the branch:
git push origin feature-name - Open a Pull Request
MIT License