Skip to content

Where The Heart Is - MVP Plan

Project Overview

A transparent mortgage calculator that reveals the hidden financial impact of homebuying decisions. Unlike typical calculators that focus on monthly payment affordability, this tool shows exactly how much interest you'll pay over a loan's lifetime, how a 1% rate difference changes your total cost, and how PMI affects your bottom line.

Core Value: Answer "what does this house actually cost me over 30 years?" instead of "can I afford the monthly payment?"

Original Project: Mike-Bros/WhereTheHeartIs


Tech Stack

Component Technology Purpose
Backend Go + Gin REST API server
Database PostgreSQL Single database for calculations
Cache Valkey (optional) Performance optimization
Frontend React + Next.js + TypeScript Modern web UI
UI Components Shadcn/ui + Tailwind Component library
Dev Environment Docker Compose Local development

Key Libraries:

  • Backend: gin-gonic/gin, jackc/pgx/v5, valkey-io/valkey-go
  • Frontend: TanStack Query, React Hook Form, Zod, Recharts

Core Features

Feature Description Notes
Mortgage Calculator Input home details, get transparent cost breakdown Real-time calculation as you type
"The Hidden Truth" Prominently show total interest, PMI costs, rate comparisons What typical calculators hide
Real-time Updates Results recalculate as you type (500ms debounce) No page refresh needed
Pin & Compare Save calculation snapshots for side-by-side comparison Client-side state only (no persistence)
Rate Range Visualization Chart showing monthly payment across interest rate range Interactive chart with tooltips
Extra Payment Scenarios Model impact of additional monthly/yearly payments Shows years saved and interest savings

Out of Scope for MVP:

  • User authentication
  • Saved calculations (persistence)
  • Event streaming (Kafka)
  • Multiple services (microservices)
  • Analytics tracking

Architecture

graph TB
    subgraph Frontend
        NX[Next.js<br/>TypeScript + Shadcn]
    end

    subgraph Backend
        API[Go API<br/>Gin Router]
    end

    subgraph Data Layer
        PG[(PostgreSQL<br/>Calculations)]
        CACHE[(Valkey<br/>Optional Cache)]
    end

    NX -->|REST API| API
    API -->|Read/Write| PG
    API -->|Cache| CACHE

API Endpoints:

  • POST /api/v1/calculate - Calculate mortgage payment
  • GET /api/v1/calculations/:id - Get calculation by ID
  • GET /health - Health check

Data Model

Calculation Inputs:

Field Type Validation Default
Home Price Currency ≥ $1 -
Down Payment Percentage 0-100% 20%
Loan Term Years ≥ 1 30
Interest Rate Percentage ≥ 0% 3.5%
Cash Savings Currency ≥ $0 -
Moving Costs Currency ≥ $0 $2,000
Closing Costs Percentage 0-100% 3%
PMI Rate Percentage 0.3-1.5% 0.5% (if < 20% down)
Extra Monthly Payment Currency ≥ $0 $0
Extra Yearly Payment Currency ≥ $0 $0

Calculation Outputs:

Output Description Display Type
Monthly Payment Principal + Interest Metric (card)
Monthly PMI PMI payment (if down payment < 20%) Metric (card)
Total Monthly Payment Payment + PMI Metric (prominent)
Total Interest Paid Lifetime interest cost Metric (prominent)
Interest at Rate -1% Savings with better rate Comparison metric
Total PMI Cost Lifetime PMI cost Metric (highlighted if >$0)
PMI End Date When PMI stops (~10 years) Metric (date)
Down Payment Amount Cash for down payment Metric (card)
Loan Amount Amount borrowed Metric (card)
Closing Costs Upfront closing costs Metric (card)
Remaining Cash Cash left after all costs Metric (card)
Payoff Time (with extra payments) Years to fully pay off loan Comparison metric
Interest Saved (with extra payments) Savings vs. standard payment schedule Comparison metric (prominent)
Equivalent Rate Effective interest rate with extra payments Comparison metric
Payment Schedule Month-by-month breakdown of principal, interest, balance Chart (line/table)
Rate Comparison Monthly payment across interest rate range Chart (line)

Mortgage Formulas

Monthly Payment (M):

M = P * [r(1 + r)^n] / [(1 + r)^n - 1]

Where:
P = Principal loan amount (home price - down payment)
r = Monthly interest rate (annual rate / 12 / 100)
n = Total number of payments (loan term in years * 12)

PMI Calculation:

Monthly PMI = (Loan amount × PMI rate) / 12

PMI applies when: Down payment % < 20%
PMI ends when: Loan balance reaches 78% of original home value (typically ~10 years)

Total PMI paid = Monthly PMI × Months until PMI ends

Derived Calculations:

  • Down payment = Home price × (Down payment % / 100)
  • Loan amount = Home price - Down payment
  • Closing costs = Home price × (Closing cost % / 100)
  • Total monthly payment = Monthly payment + Monthly PMI
  • Total payment = (Monthly payment × Number of payments) + Total PMI paid
  • Total interest = Total payment - Loan amount - Total PMI paid
  • Remaining cash = Cash savings - Down payment - Closing costs - Moving cost

Extra Payment Calculations (The True Impact):

When extra payments are made:

1. Calculate standard amortization schedule
2. Apply extra payments each period:
   - Extra monthly payment added to principal each month
   - Extra yearly payment added once per year (typically month 12)
3. Recalculate remaining balance after each payment
4. Loan is paid off when balance reaches $0
5. Interest saved = Standard total interest - Actual total interest paid
6. Years saved = Standard term - Actual payoff time

Equivalent Rate: The interest rate that would give the same monthly
payment without extra payments (reverse calculation)

Note on PMI with Extra Payments:

  • PMI ends when loan-to-value ratio reaches 78% (based on current balance)
  • Extra payments accelerate reaching this threshold
  • Must recalculate PMI end date in amortization schedule

Comparison Calculations (The Hidden Truth):

  • Interest saved with 1% lower rate = Current total interest - (total interest at rate - 1%)
  • PMI impact = Total PMI paid (shown prominently if applicable)
  • Extra payment impact = Interest saved + Years saved (shown prominently if extra payments > 0)

Implementation Milestones

Milestone 1: Project Setup

  • Initialize Go project with Gin router structure
  • Initialize Next.js project with TypeScript
  • Set up Docker Compose (PostgreSQL, Valkey, backend, frontend)
  • Configure environment variables and verify local setup

Milestone 2: Backend - Calculation API

  • Implement standard mortgage calculation logic with unit tests
  • Implement PMI calculation (when it applies, when it ends)
  • Implement extra payment amortization schedule calculation
  • Create /api/v1/calculate endpoint with input validation
  • Add database schema and migration for calculations table
  • Implement Valkey caching layer (optional)
  • Test API endpoints with curl/Postman (including extra payment scenarios)

Milestone 3: Frontend - Calculator UI

  • Create calculator form with all input fields (including extra payments)
  • Implement real-time calculation with 500ms debounce
  • Create result display component showing "The Hidden Truth"
  • Display extra payment impact (years saved, interest saved) when applicable
  • Add input validation and error handling
  • Connect to backend API with TanStack Query

Milestone 4: Pin & Compare Feature

  • Implement client-side state management for pinned results
  • Create pinned results display component (side-by-side cards)
  • Add "Pin Result" and remove functionality
  • Implement responsive layout for comparison view

Milestone 5: Visualization & Polish

  • Create rate range chart with Recharts
  • Improve mobile responsiveness
  • Add loading states and skeletons
  • Polish UI with consistent styling
  • End-to-end testing of user workflows

Project Structure

where-the-heart-is/                  # Monorepo root
├── backend/
│   ├── cmd/
│   │   └── api/
│   │       └── main.go              # Application entry point
│   ├── internal/
│   │   ├── handler/                 # HTTP handlers (Gin)
│   │   │   ├── calculate.go
│   │   │   ├── health.go
│   │   │   └── middleware/          # CORS, logging
│   │   ├── service/                 # Business logic
│   │   │   ├── calculator.go        # Mortgage calculation
│   │   │   └── cache.go             # Cache management
│   │   ├── repository/              # Data access
│   │   │   ├── postgres.go
│   │   │   └── valkey.go
│   │   ├── model/                   # Domain models
│   │   │   └── calculation.go
│   │   └── config/                  # Configuration
│   │       └── config.go
│   ├── migrations/                  # SQL migrations
│   ├── go.mod
│   └── Dockerfile
├── frontend/
│   ├── app/                         # Next.js App Router
│   │   ├── layout.tsx
│   │   └── page.tsx                 # Calculator page
│   ├── components/
│   │   ├── calculator/
│   │   │   ├── calculator-form.tsx
│   │   │   ├── result-card.tsx
│   │   │   └── pinned-results.tsx
│   │   └── ui/                      # Shadcn components
│   ├── lib/
│   │   ├── api/
│   │   │   ├── client.ts            # Axios instance
│   │   │   └── calculator.ts        # API calls
│   │   ├── hooks/
│   │   │   ├── use-calculator.ts
│   │   │   └── use-debounce.ts
│   │   ├── schemas/
│   │   │   └── calculation.ts       # Zod schemas
│   │   └── utils/
│   │       └── formatters.ts        # Currency formatting
│   ├── package.json
│   └── next.config.js
├── docker-compose.yml               # Local development
├── Makefile                         # Common tasks (migrate, seed, test)
└── README.md

Success Criteria

MVP is complete when:

  • Calculator accepts all required inputs with real-time validation
  • Mortgage calculations are mathematically correct (verified by unit tests)
  • Results update in real-time without page refresh (500ms debounce)
  • Users can pin and compare up to 5 scenarios side-by-side
  • Rate range visualization chart works correctly
  • UI is clean, intuitive, and mobile-responsive
  • Application runs locally via Docker Compose

Key Differentiators:

  • The "Hidden Truth" section prominently shows total interest paid, PMI costs, and rate comparison savings
  • Extra payment modeling shows the true impact of paying extra because most calculators don't do this well or at all
  • All hidden costs and savings are transparent and easy to compare

Document Version: 1.0 (MVP Scope)

Last Updated: 2025-10-17

Status: Ready for Implementation