Reimbursor - Expense Management System
A premium, multi-tenant expense management system built with Next.js 14, Prisma, and PostgreSQL. Designed for businesses to streamline employee expense submissions, approval workflows, and financial oversight with an enterprise-grade user experience.
Reimbursor automates the expense reimbursement process by providing:
For Employees : Easy expense submission with multi-currency support and real-time status tracking
For Managers : Multi-level approval workflows with sequential/parallel step support
For Admins : Complete visibility, powerful overrides, and user management across the organization
Category
Technology
Frontend
Next.js 14 (App Router), React 18, Tailwind CSS, shadcn/ui
Backend
Next.js API Routes, Prisma ORM
Database
PostgreSQL
Authentication
NextAuth.js (JWT Strategy)
Email
Nodemailer (SMTP)
Monitoring
Sentry
Validation
Zod
Role
Capabilities
Employee
Submit expenses, view own expense history, receive status notifications
Manager
Approve/reject team expenses, view pending approvals, see converted amounts
Admin
View all company expenses, override any approval, manage users, manage workflows
Authentication & Authorization
Multi-Level Approval Workflow
Editorial Enterprise Design System
src/
├── app/
│ ├── (app)/ # Protected routes (with navbar + sidebar)
│ │ ├── admin/
│ │ │ ├── expenses/ # Admin expense management
│ │ │ ├── users/ # User management
│ │ │ └── settings/ # Company settings
│ │ ├── approvals/ # Manager approval page
│ │ ├── dashboard/ # User dashboard
│ │ ├── expenses/ # Expense list & detail
│ │ │ ├── [id]/ # Expense detail page
│ │ │ └── new/ # Create expense
│ │ ├── notifications/ # Notification center
│ │ └── layout.tsx # App layout with navbar/sidebar
│ ├── (auth)/ # Public routes (no navbar)
│ │ ├── forgot-password/ # Password reset request
│ │ ├── login/ # Login page
│ │ ├── reset-password/ # Password reset form
│ │ ├── signup/ # Registration
│ │ └── layout.tsx # Auth layout
│ ├── api/ # API Routes
│ │ ├── auth/ # Auth endpoints
│ │ ├── approvals/ # Approval actions
│ │ ├── company/ # Company management
│ │ ├── dashboard/ # Dashboard data
│ │ ├── expenses/ # Expense CRUD & submit
│ │ ├── notifications/ # Notification management
│ │ ├── users/ # User management
│ │ └── workflow/ # Workflow management
│ ├── actions/ # Server actions
│ ├── global-error.tsx # Global error boundary
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Root redirect
│ └── providers.tsx # Session provider
├── components/
│ ├── ui/ # shadcn/ui components
│ │ ├── button.tsx # Gradient primary buttons
│ │ ├── card.tsx # Surface-based cards
│ │ ├── dialog.tsx # Glassmorphic dialogs
│ │ ├── input.tsx # Minimalist inputs
│ │ ├── table.tsx # Borderless tables
│ │ └── timeline.tsx # Approval flow timeline
│ ├── AdminExpenseTable.tsx # Admin dashboard table
│ ├── AdminOverrideDialog.tsx # Admin override modal
│ ├── CompanySetupModal.tsx # Company setup wizard
│ ├── ExpenseAmountCell.tsx # Currency display
│ ├── ExpenseList.tsx # Expense listing
│ ├── Navbar.tsx # Glassmorphic navbar
│ ├── Notifications.tsx # Notification bell & list
│ ├── Sidebar.tsx # Active sidebar
│ └── SubmitExpenseButton.tsx # Submit action
└── lib/
├── auth.ts # NextAuth configuration
├── dashboard.ts # Dashboard data fetching
├── email.ts # Email service
├── logger.ts # Logging utilities
├── notifications/ # Notification system
│ ├── eventDispatcher.ts # Event handling
│ ├── notificationService.ts
│ └── index.ts
├── prisma.ts # Prisma client
├── utils.ts # Utility functions
├── validations.ts # Zod schemas
└── workflow/ # Approval workflow engine
├── engine.ts # WorkflowEngine class
└── index.ts
Method
Endpoint
Description
POST
/api/auth/signup
Register new user & company
POST
/api/auth/forgot-password
Request password reset
POST
/api/auth/reset-password
Reset password with token
Method
Endpoint
Description
GET
/api/users
List all company users
POST
/api/users
Create new user
GET
/api/users/[id]
Get user details
PATCH
/api/users/[id]
Update user (role, manager)
DELETE
/api/users/[id]
Delete user
Method
Endpoint
Description
GET
/api/expenses
List user's expenses
POST
/api/expenses
Create new expense
GET
/api/expenses/[id]
Get expense details
POST
/api/expenses/[id]/submit
Submit for approval
Method
Endpoint
Description
GET
/api/approvals
Get pending approvals
POST
/api/approvals
Approve or reject expense
Method
Endpoint
Description
GET
/api/workflow
Get workflow configuration
POST
/api/workflow
Create workflow
PATCH
/api/workflow/[id]
Update workflow
Method
Endpoint
Description
GET
/api/notifications
Get user notifications
PATCH
/api/notifications
Mark as read
Company - Multi-tenant organization
User - Employees with roles and manager relationships
Expense - Expense claims with multi-currency support
ApprovalWorkflow - Company-level workflow configurations
ApprovalStep - Individual steps with type, thresholds, approvers
ApprovalAction - Individual approval decisions with idempotency
Notification - User notifications with idempotency
Receipt - Attached receipt files
SendPasswordToken - Password reset tokens
@@index ([employeeId , status ] ) // Expense
@@index ([companyId , status ] ) // Expense
@@index ([createdAt ] ) // Expense
@@index ([userId , read ] ) // Notification
@@index ([userId , createdAt ] ) // Notification
@@index ([approverId , action ] ) // ApprovalAction
@@index ([expenseId , stepOrder ] ) // ApprovalAction
@@index ([workflowId , stepOrder ] ) // ApprovalStep
# Database
DATABASE_URL = " postgresql://..."
# Auth
AUTH_SECRET = " your-secret"
NEXTAUTH_SECRET = " your-secret"
NEXTAUTH_URL = " http://localhost:3000"
# Email (SMTP)
SMTP_HOST = " smtp.example.com"
SMTP_PORT = " 587"
SMTP_USER = " user"
SMTP_PASS = " password"
EMAIL_FROM = " noreply@example.com"
# Optional
DEFAULT_COUNTRY = " United States"
NEXT_PUBLIC_SENTRY_DSN = " "
Node.js 18+
PostgreSQL database
SMTP server (optional)
# Install dependencies
npm install
# Generate Prisma client
npx prisma generate
# Push schema to database
npx prisma db push
# Start development server
npm run dev
Performance Optimizations
Parallel Queries - Dashboard loads data with Promise.all
Database Indexes - Optimized for common queries
Selective Fields - Only fetch required data
Idempotent Operations - Prevent duplicate processing
Event-driven Notifications - Decoupled from business logic
Memoized Filters - Client-side filtering with useMemo
Password hashing with bcrypt
JWT session strategy
Role-based middleware protection
Input validation with Zod
SQL injection prevention (Prisma)
Idempotency keys for critical operations