- Added documentation for architecture and code plan - Implemented database schema for users, expenses, settlements, and transactions - Set up double-entry bookkeeping system with multi-currency support - Configured Hono web framework with middleware - Integrated Drizzle ORM for database operations
8.4 KiB
8.4 KiB
Splitwise Application - Code Plan
This document outlines the technical architecture, stack, and implementation plan for our Splitwise-style expense-splitting application.
Tech Stack
Frontend
- Runtime: Bun
- Framework: React 18+ with TypeScript
- Build Tool: Vite
- Styling: TailwindCSS with Shadcn UI component library
- State Management: Zustand
- Data Fetching: TanStack Query (React Query)
- Form Handling: React Hook Form with Zod validation
- Routing: React Router v6
- Testing: Vitest, React Testing Library
- Components: Shadcn UI (customizable Radix UI-based components)
Backend
- Runtime: Bun
- Language: TypeScript
- Framework: Hono (lightweight, fast, TypeScript-first)
- Database: PostgreSQL
- ORM: Drizzle (TypeScript-first ORM)
- Authentication: better-auth (framework-agnostic authentication with email/password and social sign-on)
- Validation: Zod
- File Storage: Local storage with Sharp for image processing (can be migrated to S3 later)
- Testing: Bun test
Architecture Overview
We'll implement a clean architecture with separation of concerns:
Frontend Architecture
- Application Layer: React components, hooks, and contexts
- Domain Layer: Zustand stores and business logic
- Infrastructure Layer: API clients and external service integrations
Key Frontend Modules:
- Auth Module: Sign-up, sign-in, profile management
- Expenses Module: Create, edit, delete expenses
- Settlements Module: Balances, settle up functionality
- Activity Module: Feed of expense and settlement activities
- Notifications Module: In-app notifications
- Settings Module: User preferences and application settings
Backend Architecture
- API Layer: Hono routes and controllers
- Service Layer: Business logic and core application services
- Data Access Layer: Drizzle ORM models and repositories
- Domain Layer: Entity definitions and domain logic
Key Backend Modules:
- Auth Module: User authentication and authorization
- Users Module: User management and profiles
- Contacts Module: Contact relationships and invitations
- Expenses Module: Expense tracking and splits
- Settlements Module: Balance calculations and settlements
- Notifications Module: Notification generation and delivery
- Files Module: Receipt image upload and processing
Database Schema (Initial)
Users
- id: uuid (primary key)
- email: string (unique)
- display_name: string
- profile_photo_url: string (nullable)
- default_currency: string (default: 'USD')
- locale: string (default: 'en-US')
- timezone: string (default: 'UTC')
- created_at: timestamp
- updated_at: timestamp
Auth (managed by better-auth)
- id: uuid (primary key)
- user_id: uuid (foreign key -> Users.id)
- provider: string (e.g., 'email', 'google', 'github')
- provider_user_id: string (nullable, for social providers)
- email: string
- password_hash: string (nullable, for email provider)
- refresh_token: string (nullable)
- last_login: timestamp
- created_at: timestamp
- updated_at: timestamp
Contacts
- id: uuid (primary key)
- user_id: uuid (foreign key -> Users.id)
- contact_id: uuid (foreign key -> Users.id)
- status: enum ('pending', 'accepted', 'declined')
- created_at: timestamp
- updated_at: timestamp
Expenses
- id: uuid (primary key)
- title: string
- amount: decimal
- date: timestamp
- payer_id: uuid (foreign key -> Users.id)
- memo: text (nullable)
- receipt_image_url: string (nullable)
- created_at: timestamp
- updated_at: timestamp
ExpenseParticipants
- id: uuid (primary key)
- expense_id: uuid (foreign key -> Expenses.id)
- user_id: uuid (foreign key -> Users.id)
- share_amount: decimal
- created_at: timestamp
- updated_at: timestamp
Settlements
- id: uuid (primary key)
- payer_id: uuid (foreign key -> Users.id)
- receiver_id: uuid (foreign key -> Users.id)
- amount: decimal
- date: timestamp
- memo: text (nullable)
- created_at: timestamp
- updated_at: timestamp
Notifications
- id: uuid (primary key)
- user_id: uuid (foreign key -> Users.id)
- type: enum ('expense_added', 'expense_edited', 'settlement_received')
- content: jsonb
- is_read: boolean (default: false)
- created_at: timestamp
API Endpoints
Authentication (managed by better-auth)
- POST /api/auth/register
- POST /api/auth/login
- POST /api/auth/social/:provider
- POST /api/auth/social/:provider/callback
- POST /api/auth/logout
- GET /api/auth/me
- POST /api/auth/refresh-token
- POST /api/auth/forgot-password
- POST /api/auth/reset-password
Users
- GET /api/users/profile
- PUT /api/users/profile
- PUT /api/users/settings
Contacts
- GET /api/contacts
- POST /api/contacts
- PUT /api/contacts/:id
- DELETE /api/contacts/:id
Expenses
- GET /api/expenses
- POST /api/expenses
- GET /api/expenses/:id
- PUT /api/expenses/:id
- DELETE /api/expenses/:id
- POST /api/expenses/:id/receipt
Balances
- GET /api/balances
- GET /api/balances/:contactId
Settlements
- POST /api/settlements
- GET /api/settlements
- GET /api/settlements/:id
Notifications
- GET /api/notifications
- PUT /api/notifications/:id/read
- PUT /api/notifications/read-all
Implementation Plan
Phase 1: Project Setup
- Initialize frontend and backend projects with Bun
- Set up TypeScript configuration
- Configure Vite for the frontend
- Install and configure Shadcn UI with TailwindCSS
- Set up Hono for the backend
- Configure Drizzle ORM with PostgreSQL
- Set up development environment with Docker for database
Phase 2: Core Authentication
- Install and configure better-auth library
- Set up authentication adapters for Hono and PostgreSQL
- Configure email/password and social sign-on providers
- Create authentication forms on frontend
- Implement profile management
Phase 3: Expense Tracking
- Implement expense CRUD operations on backend
- Create expense form components on frontend
- Implement expense splitting logic
- Add receipt image upload functionality
Phase 4: Balances and Settlements
- Implement balance calculation logic
- Create settlement endpoints
- Build balance visualization components
- Implement settlement UI
Phase 5: Activity Feed and Notifications
- Create activity tracking for expenses and settlements
- Implement notification generation
- Build activity feed UI
- Add in-app notification components
Phase 6: Settings and Refinement
- Implement user settings
- Add locale and currency formatting
- Refine UI/UX
- Performance optimizations
Folder Structure
Frontend
frontend/
├── public/
├── src/
│ ├── assets/
│ ├── components/
│ │ ├── auth/
│ │ ├── expenses/
│ │ ├── settlements/
│ │ ├── activity/
│ │ ├── notifications/
│ │ ├── settings/
│ │ └── ui/
│ ├── hooks/
│ │ └── useBetterAuth.ts
│ ├── pages/
│ ├── services/
│ │ ├── api.ts
│ │ └── auth.ts
│ ├── stores/
│ ├── types/
│ ├── utils/
│ ├── lib/
│ │ └── shadcn-ui/
│ ├── styles/
│ │ └── globals.css
│ ├── App.tsx
│ └── main.tsx
├── components.json
├── tailwind.config.js
├── .env
├── package.json
└── tsconfig.json
Backend
backend/
├── src/
│ ├── controllers/
│ ├── db/
│ │ ├── schema/
│ │ └── migrations/
│ ├── middleware/
│ ├── services/
│ ├── auth/
│ │ ├── config.ts
│ │ ├── providers/
│ │ └── adapters/
│ ├── types/
│ ├── utils/
│ └── index.ts
├── .env
├── package.json
└── tsconfig.json
Getting Started
Prerequisites
- Bun installed
- PostgreSQL database
- Node.js 18+ (for additional tools)
Setup Instructions
- Clone the repository
- Install dependencies for both frontend and backend with
bun install - Set up environment variables (.env files)
- Run database migrations with Drizzle
- Start the development servers:
- Frontend:
bun run dev - Backend:
bun run dev
- Frontend:
Development Practices
- TypeScript for type safety
- Feature branch workflow
- Write tests for critical functionality
- Use Zod schemas for validation and type inference
- Follow REST principles for API design
- Document API endpoints with JSDoc or Swagger