Files
splitwise/docs/code-plan.md
Yadunand Prem 74b7ddf3d6 feat: initial backend setup with Bun, Hono, and Drizzle ORM
- 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
2025-05-27 17:38:50 -04:00

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:

  1. Auth Module: Sign-up, sign-in, profile management
  2. Expenses Module: Create, edit, delete expenses
  3. Settlements Module: Balances, settle up functionality
  4. Activity Module: Feed of expense and settlement activities
  5. Notifications Module: In-app notifications
  6. 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:

  1. Auth Module: User authentication and authorization
  2. Users Module: User management and profiles
  3. Contacts Module: Contact relationships and invitations
  4. Expenses Module: Expense tracking and splits
  5. Settlements Module: Balance calculations and settlements
  6. Notifications Module: Notification generation and delivery
  7. 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

  1. Initialize frontend and backend projects with Bun
  2. Set up TypeScript configuration
  3. Configure Vite for the frontend
  4. Install and configure Shadcn UI with TailwindCSS
  5. Set up Hono for the backend
  6. Configure Drizzle ORM with PostgreSQL
  7. Set up development environment with Docker for database

Phase 2: Core Authentication

  1. Install and configure better-auth library
  2. Set up authentication adapters for Hono and PostgreSQL
  3. Configure email/password and social sign-on providers
  4. Create authentication forms on frontend
  5. Implement profile management

Phase 3: Expense Tracking

  1. Implement expense CRUD operations on backend
  2. Create expense form components on frontend
  3. Implement expense splitting logic
  4. Add receipt image upload functionality

Phase 4: Balances and Settlements

  1. Implement balance calculation logic
  2. Create settlement endpoints
  3. Build balance visualization components
  4. Implement settlement UI

Phase 5: Activity Feed and Notifications

  1. Create activity tracking for expenses and settlements
  2. Implement notification generation
  3. Build activity feed UI
  4. Add in-app notification components

Phase 6: Settings and Refinement

  1. Implement user settings
  2. Add locale and currency formatting
  3. Refine UI/UX
  4. 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

  1. Clone the repository
  2. Install dependencies for both frontend and backend with bun install
  3. Set up environment variables (.env files)
  4. Run database migrations with Drizzle
  5. Start the development servers:
    • Frontend: bun run dev
    • Backend: bun run dev

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