A secure, full-stack banking application with user authentication, account management, and transaction processing with immutable ledger tracking.
- Node.js with Express.js
- MongoDB database with Mongoose ODM
- Clerk authentication integration
- EmailJS for email notifications
- CORS enabled for cross-origin requests
- React 19 with Vite
- TypeScript/JavaScript with React Router
- Tailwind CSS for styling
- Radix UI component library
- Clerk React SDK for authentication
- Sonner for toast notifications
- Lucide React for icons
- Clerk-based user authentication and account management
- Secure API routes with custom middleware authentication using x-clerk-id header
- User profile synchronization from Clerk to database
- User registration and profile creation
- User data synchronization from Clerk
- Profile information retrieval
- Email notifications on account registration
- Create new bank accounts with currency support
- View all user accounts
- Account status management (ACTIVE, FROZEN, CLOSED)
- Real-time balance calculation from ledger entries
- Account details and metadata
- Money transfer between accounts
- Idempotency key support for safe transaction retry
- Transaction status tracking (PENDING, COMPLETED, FAILED, REVERSED)
- Email notifications for successful and failed transactions
- Transaction history with timestamps
- Secure authorization checks for account ownership
- Immutable ledger entries for audit trail
- Double-entry bookkeeping (DEBIT/CREDIT)
- Real-time balance calculations from ledger
- Complete transaction history per account
- Ledger entries cannot be updated or deleted, only new entries can be created
- Overview of total balance across all accounts
- Count of active accounts
- Recent transactions display
- Quick access to key features
- Home: Landing page with feature overview and call-to-action
- Dashboard: Main user hub with account summaries and recent activity
- Accounts: Manage accounts, view balances, create new accounts
- Transfer: Execute money transfers between accounts with confirmation
- History: View complete transaction ledger with filtering and pagination
- Profile: User information display and account settings
backend/
βββ src/
β βββ config/
β β βββ db.js # MongoDB connection
β βββ controllers/
β β βββ user.controller.js # User management logic
β β βββ account.controller.js # Account operations
β β βββ transaction.controller.js # Transaction processing
β βββ middleware/
β β βββ auth.middleware.js # Request authentication
β βββ models/
β β βββ user.model.js # User schema
β β βββ account.model.js # Account schema
β β βββ transaction.model.js # Transaction schema
β β βββ ledger.model.js # Immutable ledger schema
β βββ plugins/
β β βββ immutable-ledger.plugin.js # Ledger immutability enforcement
β βββ routes/
β β βββ user.routes.js # User endpoints
β β βββ account.routes.js # Account endpoints
β β βββ transaction.routes.js # Transaction endpoints
β βββ services/
β βββ email.service.js # Email notification service
βββ server.js # Express app initialization
βββ package.json
frontend/
βββ src/
β βββ components/
β β βββ Layout.jsx # Main layout wrapper
β β βββ Navbar.jsx # Navigation bar
β β βββ Footer.jsx # Footer
β β βββ ui/ # Radix UI components
β βββ pages/
β β βββ Home.jsx # Landing page
β β βββ Dashboard.jsx # Main dashboard
β β βββ Accounts.jsx # Account management
β β βββ Transfer.jsx # Money transfer
β β βββ History.jsx # Transaction history
β β βββ Profile.jsx # User profile
β β βββ Admin.jsx # Admin interface
β β βββ AdminPanel.jsx # Admin panel
β βββ services/
β β βββ apiService.js # Backend API client
β βββ hooks/
β β βββ useSyncUserToDatabase.js # User sync hook
β βββ App.jsx # Main app component
β βββ main.jsx # React entry point
βββ package.json
- Node.js (v16 or higher)
- MongoDB (local or MongoDB Atlas)
- EmailJS account (for email notifications)
- Clerk account (for authentication)
- Navigate to backend directory:
cd backend- Install dependencies:
npm install- Create
.envfile:
cp .env.example .env- Configure environment variables:
MONGODB_URI=your_mongodb_connection_string
PORT=5000
FRONTEND_URL=http://localhost:5173
# EmailJS Configuration
EMAILJS_SERVICE_ID=your_service_id
EMAILJS_TEMPLATE_ID_REGISTRATION=your_template_id
EMAILJS_TEMPLATE_ID_TRANSACTION=your_template_id
EMAILJS_PUBLIC_KEY=your_public_key
EMAILJS_PRIVATE_KEY=your_private_key
# Ledger immutability setting
LEDGER_IMMUTABLE=true
- Start development server:
npm run devServer runs on http://localhost:5000
- Navigate to frontend directory:
cd frontend- Install dependencies:
npm install- Create
.envfile:
VITE_API_URL=http://localhost:5000/api
VITE_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key- Start development server:
npm run devFrontend runs on http://localhost:5173
http://localhost:5000/api
All authenticated endpoints require:
x-clerk-id: your_clerk_id
POST /users/save Create or update user (sync from Clerk)
- Request:
{clerkId, email, firstName, lastName, profileImage} - Response: User object with metadata
GET /users/ Get all users (requires authentication)
- Response: Array of user objects
GET /users/:clerkId Get user by Clerk ID (requires authentication)
- Response: Single user object
POST /accounts/create Create new account (requires authentication)
- Request:
{currency: "INR", status: "ACTIVE"} - Response: Account object
GET /accounts/ Get all user accounts (requires authentication)
- Response: Array of account objects for authenticated user
GET /accounts/:accountId Get specific account (requires authentication)
- Response: Single account object
GET /accounts/:accountId/balance Get account balance (requires authentication)
- Response:
{balance: number}
GET /accounts/:accountId/ledger Get account ledger entries (requires authentication)
- Response: Array of ledger entries
GET /accounts/ledger/all Get all ledger entries for user (requires authentication)
- Response: Array of all ledger entries across accounts
PUT /accounts/:accountId/status Update account status (requires authentication)
- Request:
{status: "ACTIVE|FROZEN|CLOSED"} - Response: Updated account object
DELETE /accounts/:accountId Soft delete account (requires authentication)
- Response: Confirmation message
POST /transactions/create Create transaction (requires authentication)
- Request:
{fromAccount, toAccount, amount, idempotencyKey} - Response: Transaction object with status
GET /transactions/ Get all user transactions (requires authentication)
- Response: Array of transaction objects
GET /transactions/:transactionId Get transaction by ID (requires authentication)
- Response: Single transaction object
PUT /transactions/:transactionId/status Update transaction status (requires authentication)
- Request:
{status: "COMPLETED|FAILED|REVERSED"} - Response: Updated transaction object
- All ledger entries are immutable by default
- Cannot be updated or deleted after creation
- Reversals create new ledger entries instead
- Enforced via plugin middleware on Mongoose schema
- Transaction creation supports idempotency keys
- Prevents duplicate transactions on retry
- Unique index on idempotencyKey field
- All transactions create DEBIT entry on source account
- All transactions create CREDIT entry on destination account
- Ledger entries track currency, amount, timestamp, and relationship
- Registration confirmation emails sent via EmailJS
- Transaction success notifications
- Failed transaction notifications
- Graceful failure if email service unavailable
- ACTIVE: Account can send and receive transactions
- FROZEN: Account restricted from operations
- CLOSED: Account marked for closure
- Status validation on transaction operations
The backend is configured with Vercel serverless functions:
api/index.jsserves as the entry pointserver.jsexports the Express app- CORS configured for deployed frontend URL
The frontend is configured with Vite and Vercel:
- Environment variables configured in Vercel dashboard
- Build optimization with Vite
- Static file serving with Vercel CDN
- clerkId (unique, required)
- email (unique, required)
- firstName (optional)
- lastName (optional)
- profileImage (optional)
- isSystemUser (immutable flag)
- timestamps (createdAt, updatedAt)
- user (reference to User)
- status (ACTIVE, FROZEN, CLOSED)
- currency (default: INR)
- timestamps (createdAt, updatedAt)
- fromAccount (reference to Account)
- toAccount (reference to Account)
- amount (required, min 0)
- status (PENDING, COMPLETED, FAILED, REVERSED)
- idempotencyKey (unique, required)
- timestamps (createdAt, updatedAt)
- account (reference to Account)
- transaction (reference to Transaction)
- direction (DEBIT or CREDIT)
- amount (required, min 0)
- currency (required)
- note (optional)
- timestamps (createdAt, updatedAt)
- IMMUTABLE (cannot be updated after creation)
cd backend
npm test- ESLint configured for JavaScript
- Use consistent formatting across codebase
- Follow established patterns in controller and service files
Backend:
npm run buildFrontend:
npm run build- Create feature branches from main
- Follow existing code patterns and structure
- Ensure all endpoints are properly authenticated
- Add email notifications for user-facing operations
- Maintain immutability of ledger entries
ISC