{"id":51240836,"url":"https://github.com/alkiory/budgetgenius","last_synced_at":"2026-06-29T00:02:18.972Z","repository":{"id":364405815,"uuid":"1267755538","full_name":"alkiory/BudgetGenius","owner":"alkiory","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-21T11:56:26.000Z","size":980,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-21T14:07:46.592Z","etag":null,"topics":["fullstack-development","hexagonal-architecture","typescript"],"latest_commit_sha":null,"homepage":"https://budgetgeniusia.web.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alkiory.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-12T20:44:12.000Z","updated_at":"2026-06-21T11:56:29.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/alkiory/BudgetGenius","commit_stats":null,"previous_names":["alkiory/budgetgenius"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/alkiory/BudgetGenius","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alkiory%2FBudgetGenius","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alkiory%2FBudgetGenius/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alkiory%2FBudgetGenius/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alkiory%2FBudgetGenius/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alkiory","download_url":"https://codeload.github.com/alkiory/BudgetGenius/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alkiory%2FBudgetGenius/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34907985,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fullstack-development","hexagonal-architecture","typescript"],"created_at":"2026-06-29T00:02:17.893Z","updated_at":"2026-06-29T00:02:18.963Z","avatar_url":"https://github.com/alkiory.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BudgetGenius\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eSmart personal finance management — track expenses, set budgets, and achieve your financial goals with AI-powered insights.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/status-active-brightgreen\" alt=\"Status\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/license-UNLICENSED-blue\" alt=\"License\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen\" alt=\"Node\" /\u003e\n\u003c/p\u003e\n\n---\n\n## 📖 Table of Contents\n\n- [Overview](#-overview)\n- [Architecture](#-architecture)\n- [Tech Stack](#-tech-stack)\n- [Features](#-features)\n- [Getting Started](#-getting-started)\n- [Web Development Workflow](#-web-development-workflow)\n- [Mobile Development](#-mobile-development)\n- [CI/CD \u0026 Deployment](#-cicd--deployment)\n- [Testing](#-testing)\n- [RPI Development Framework](#-rpi-development-framework)\n- [Project Structure](#-project-structure)\n- [Environment Variables](#-environment-variables)\n- [API Documentation](#-api-documentation)\n- [Contributing](#-contributing)\n\n---\n\n## 📋 Overview\n\nBudgetGenius is a full-stack web application that helps users manage their personal finances through an intuitive budgeting tool. Users can track income and expenses, create custom budgets with categories, set savings goals, monitor progress with visual dashboards, and receive AI-powered financial insights from \"Finny\", our bilingual financial assistant.\n\nThe application follows a **Clean Architecture** pattern across both its frontend and backend, with strict layer separation ensuring maintainable, testable code.\n\n### Core Capabilities\n\n- **Expense \u0026 Income Tracking** — Log, categorize, and monitor all financial transactions\n- **Budget Planning** — Create custom budgets with categorized allocations and real-time spending tracking\n- **Financial Goals** — Set short-term and long-term goals with progress visualization\n- **Savings Goals** — Track saving progress with target dates and percentage completion *(Premium)*\n- **Investment Tracking** — Monitor investment portfolio performance *(Premium)*\n- **Reports \u0026 Analytics** — Generate detailed financial reports with charts *(Premium)*\n- **AI Financial Assistant (\"Finny\")** — Get personalized insights and advice powered by OpenAI\n- **Multi-Authentication** — Email/password, Google OAuth 2.0, and Firebase authentication\n- **Bilingual Support** — Full English \u0026 Spanish support across the AI assistant\n\n---\n\n## 🏗 Architecture\n\n![alt text](image.png)\n\n```\n                        ┌──────────────────────┐\n                        │     webClient         │\n                        │   React 19 + Vite 6   │\n                        │   Tailwind + Recharts │\n                        │      Port 3001        │\n                        └───────────┬───────────┘\n                                    │ HTTP (axios)\n                                    │\n                        ┌───────────▼───────────┐\n                        │         api           │\n                        │      NestJS 10        │\n                        │  TypeORM + Passport   │\n                        │      Port 3000        │\n                        └───┬───────┬───────┬───┘\n                            │       │       │\n                    ┌───────▼──┐ ┌──▼───┐ ┌▼──────┐\n                    │PostgreSQL│ │Redis │ │OpenAI │\n                    │   15     │ │ 7.2  │ │  GPT  │\n                    └──────────┘ └──────┘ └───────┘\n```\n\n### Layered Architecture (Clean Architecture)\n\nBoth apps follow the same layered architecture with strict dependency rules:\n\n| Layer | Responsibility | Backend Path | Frontend Path |\n|-------|---------------|-------------|--------------|\n| **Domain** | Entities, repository interfaces, value objects | `src/domain/` | `src/domain/` |\n| **Application** | Business logic, service orchestration | `src/application/` | `src/application/` |\n| **Infrastructure** | Technical details: config, modules, middleware | `src/infrastructure/` | `src/infrastructure/` |\n| **Adapters** | External interfaces: controllers, HTTP repositories | `src/adapters/` | `src/adapters/` |\n| **Presentation** | UI components, pages, layouts, routes | — | `src/presentation/` |\n\n*Dependencies always point inward — Domain never imports from outer layers.*\n\n### Monorepo Structure\n\nThis project uses a **pnpm workspace monorepo** with **Turbo** for build orchestration:\n\n```\nBudgetGenius/\n├── apps/\n│   ├── api/              # NestJS backend (TypeScript)\n│   ├── webClient/        # React frontend (TypeScript + Vite)\n│   └── mobile/           # Capacitor native wrapper (Android APK)\n├── docs/\n│   └── rpi/              # RPI Development Framework docs\n├── scripts/\n│   └── bootstrap.sh      # One-command setup\n├── docker-compose.yml     # Base Docker services\n├── docker-compose.dev.yml # Development overrides\n├── docker-compose.prod.yml# Production overrides\n└── turbo.json             # Turbo pipeline config\n```\n\n---\n\n## 🛠 Tech Stack\n\n### Backend (`apps/api`)\n| Technology | Purpose |\n|-----------|---------|\n| **NestJS 10** | Server-side framework with modular architecture |\n| **TypeScript 5.7** | Type-safe development |\n| **TypeORM 0.3** | Object-Relational Mapping for PostgreSQL |\n| **PostgreSQL 15** | Primary relational database |\n| **Redis 7.2** | Caching, session store, rate limiting, AI history |\n| **Passport.js** | Authentication middleware (JWT + Google OAuth) |\n| **Firebase Admin SDK** | Firebase token verification |\n| **OpenAI SDK** | AI financial assistant integration |\n| **Swagger/OpenAPI** | Auto-generated API documentation |\n| **Winston + Morgan** | Structured logging and HTTP request logging |\n\n### Frontend (`apps/webClient`)\n| Technology | Purpose |\n|-----------|---------|\n| **React 19** | UI library with functional components |\n| **Vite 6** | Fast development server and build tool |\n| **TypeScript 5.7** | Type-safe development |\n| **Tailwind CSS 3** | Utility-first CSS framework |\n| **Redux Toolkit** | Client-side state management (auth, settings) |\n| **React Query (TanStack)** | Server state management and caching |\n| **React Router 7** | Client-side routing with lazy loading |\n| **Recharts** | Composable charting library |\n| **Lucide React** | Icon library |\n| **Axios** | HTTP client with interceptors |\n\n### Mobile (`apps/mobile`)\n| Technology | Purpose |\n|-----------|---------|\n| **Capacitor 7** | Native wrapper for Android (and iOS) — wraps the Vite build output |\n| **@capgo/capacitor-social-login** | Native Android Credential Manager plugin (replaces the older `@capacitor-firebase/authentication` flow which opened Chrome Custom Tabs — see `docs/changelog.md` v1.2.0) |\n| **Android Gradle** | Build system for Android APK generation |\n\n### DevOps \u0026 Infrastructure\n| Technology | Purpose |\n|-----------|---------|\n| **Docker + Docker Compose** | Containerized development and deployment |\n| **GitHub Actions** | CI/CD pipeline (test, build, deploy) |\n| **Turbo** | Monorepo task orchestration |\n| **pnpm** | Fast, disk-efficient package manager |\n| **Vercel** | Frontend hosting |\n| **Firebase Hosting** | Static asset hosting |\n| **AWS RDS** | Managed PostgreSQL (production) |\n| **Playwright** | End-to-end browser testing |\n| **Jest** | Backend unit and e2e testing |\n\n---\n\n## ✨ Features\n\n### 🔐 Authentication \u0026 Authorization\n- Multi-provider auth: Email/Password, Google OAuth 2.0, Firebase\n- JWT access tokens (1h) with refresh token rotation (7d in Redis)\n- Rate limiting: 4 requests per 10 seconds per device\n- Role-based access control (User/Admin)\n- Premium feature gating\n\n### 💰 Transaction Management\n- Full CRUD operations on transactions\n- Categorization and status tracking\n- Date-based filtering and sorting\n- Paginated transaction lists\n\n### 📊 Budget Planning\n- Create budgets with custom date ranges\n- Category-based allocation tracking\n- Real-time spending vs. allocated comparison\n- Visual progress indicators\n\n### 🎯 Financial Goals\n- Short-term and long-term goal tracking\n- Target amounts with current progress\n- Contribution frequency settings\n- Visual percentage completion\n\n### 💎 Premium Features\n- Savings goals with color-coded progress\n- Detailed financial reports and analytics\n- Investment portfolio tracking\n\n### 🤖 AI Financial Assistant (\"Finny\")\n- Context-aware financial advice\n- Bilingual (English/Spanish) interaction\n- Conversation history stored in Redis\n- System prompt tailored to user's financial data\n\n### 🌐 Localization\n- Currency, timezone, and locale preferences per user\n- Bilingual AI responses\n\n---\n\n## 🚀 Getting Started\n\n### Prerequisites\n\n- **Node.js** v18 or higher\n- **pnpm** v10.x (install: `npm install -g pnpm`)\n- **Docker** \u0026 **Docker Compose** (for PostgreSQL and Redis)\n\n---\n\n### First-Time Setup\n\n#### Option A: Quick Start with Bootstrap (Recommended)\n\nThis single command handles everything:\n\n```bash\ngit clone \u003crepository-url\u003e\ncd BudgetGenius\nchmod +x scripts/bootstrap.sh\n./scripts/bootstrap.sh\n```\n\nThe bootstrap script automates:\n1. ✅ Checks prerequisites (Node.js, pnpm)\n2. ✅ Installs all workspace dependencies via `pnpm install`\n3. ✅ Creates `.env.development` from templates with generated JWT secret\n4. ✅ Starts Docker services (PostgreSQL + Redis) via `docker compose`\n5. ✅ Builds backend and frontend container images\n\n#### Option B: Manual Setup\n\n```bash\n# 1. Install dependencies\npnpm install\n\n# 2. Create environment files\ncp apps/api/.env.example apps/api/.env.development\ncp apps/webClient/.env.example apps/webClient/.env.development\n\n# 3. Edit apps/api/.env.development with your values:\n#    - Set JWT_SECRET (generate: openssl rand -hex 32)\n#    - DB_HOST=localhost, DB_USER=postgres_admin_dev\n#    - DB_PASS=dev_password, DB_NAME=budgetgenius_dev\n#    - REDIS_HOST=localhost, REDIS_PORT=6379\n\n# 4. Start Docker services (PostgreSQL + Redis only)\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d database redis\n```\n\n---\n\n### After Bootstrap — What's Next?\n\nOnce the bootstrap script finishes (or you start Docker manually), follow these steps in order:\n\n#### 1. Verify Services are Running\n\n```bash\n# Check that PostgreSQL and Redis are healthy\ndocker ps --filter name='bg-'\n\n# Expected output:\n# bg-db-dev     ... (healthy)    ports: 5432\n# bg-redis-dev  ... (healthy)    ports: 6379\n```\n\n#### 2. Run Database Migrations\n\nMigrations create the required tables in the `bg_public` schema:\n\n```bash\npnpm --filter api migration:run\n```\n\n\u003e **Note:** If you used the full bootstrap (which starts all Docker containers), the Docker backend auto-runs migrations on startup — so they're already applied. Running this again locally is safe; it will simply report \"no pending migrations.\" If you only started `database` and `redis` containers (without the backend), you'll need to run migrations manually here.\n\u003e\n\u003e ❗ **If this command fails with `EAI_AGAIN database` or `password authentication failed`**, your shell may have stale environment variables from an old root `.env` file. See the [Stale Environment Variables](#️-common-pitfall-stale-environment-variables) section below to fix it.\n\n#### 3. Start the Development Servers\n\n```bash\npnpm dev\n```\n\nThis starts both the **NestJS backend** and the **Vite frontend** with hot reload via Turbo.\n\n#### 4. Access the Application\n\n| Service | URL (Mode A — local dev) | URL (Mode B — Docker) | Description |\n|---------|--------------------------|----------------------|-------------|\n| 🌐 **Frontend** | http://localhost:5173 (Vite) | http://localhost:3001 (nginx) | React SPA |\n| 🚂 **Backend API** | http://localhost:5000 | http://localhost:3000 | NestJS REST API (binds `process.env.PORT \\|\\| 5000`, see `apps/api/src/main.ts`) |\n| 📚 **Swagger Docs** | http://localhost:5000/docs | http://localhost:3000/docs | Interactive API documentation |\n| 🐘 **PostgreSQL** | localhost:5432 | localhost:5432 (via Docker port mapping) | Schema `bg_public` (`user: postgres_admin_dev`, `pass: dev_password`, `db: budgetgenius_dev`) |\n| 🔴 **Redis** | localhost:6379 | localhost:6379 (via Docker port mapping) | Cache, refresh tokens, throttle buckets |\n\n\u003e **Wave 1 [T1.6] reconciliation note:** the architecture diagram and this table show **both Mode A and Mode B** ports side-by-side. Mode A = `pnpm dev` (Vite + `nest start`, hot reload). Mode B = `docker compose up` (nginx + image-baked NestJS). The `.env.development` files always keep *Mode A* defaults (`localhost:5000` for backend); Docker overrides them to `redis`/`database` hostnames via `docker-compose.dev.yml`.\n\n#### 5. Default Users (Auto-Seeded)\n\nOn first startup, the backend automatically creates two test users:\n\n| Role | Email | Password | Premium? |\n|------|-------|----------|----------|\n| 👑 **Admin** | `admin@admin.com` | `#Password123` | ✅ Yes |\n| 👤 **User** | `normal@normal.com` | `#Password123` | ❌ No |\n\nYou can log in with either account immediately.\n\n---\n\n## 💻 Web Development Workflow\n\n### Daily Development Cycle\n\nEach time you come back to work on the project:\n\n```bash\n# 1. Start Docker services (if not already running)\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d database redis\n\n# 2. Run any new migrations (if entities were changed)\npnpm --filter api migration:run\n\n# 3. Start the dev servers\npnpm dev\n```\n\n### 🐳 Two Development Modes\n\nThe project supports two complementary workflows. Choose based on what you need:\n\n#### Mode A: Docker for Data Services + Local Dev Servers (Recommended)\n\n```bash\n# Terminal 1 — Start only PostgreSQL and Redis in Docker\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d database redis\n\n# Terminal 2 — Start backend and frontend with hot reload\npnpm dev\n```\n\n\u003e **⚠️ Important:** In this mode, the backend runs on port **5000** (not 3000). Make sure your frontend `.env.development` has `VITE_API_URL=http://localhost:5000/api`. If you ran `pnpm bootstrap` and chose \"Y\" for Docker, it set `VITE_API_URL=http://localhost:3000/api` — edit it to port 5000 for Mode A.\n\n**Why choose this?**\n- ✅ Hot reload on code changes (NestJS watches for file changes)\n- ✅ Faster iteration — no need to rebuild Docker images\n- ✅ Full TypeScript debugging support\n- ✅ Frontend served by Vite dev server on port 5173 or by nginx on port 3001\n\n#### Mode B: Everything in Docker (CI/Production-like)\n\n```bash\n# Build and start all containers\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build\n\n# View logs\ndocker compose logs -f\n```\n\n**Why choose this?**\n- ✅ Exact replica of production environment\n- ✅ Migrations run automatically on container start\n- ✅ Useful for testing Docker-specific issues\n- ❌ No hot reload — you must rebuild the image for each code change\n\n---\n\n### Stopping Everything\n\n```bash\n# Stop dev servers — press Ctrl+C in the terminal running pnpm dev\n\n# Stop Docker services (data persists in named volumes)\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml down\n\n# Stop Docker services AND delete all data (reset database)\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml down -v\n```\n\n---\n\n### ⚠️ Common Pitfall: Stale Environment Variables\n\nDocker Compose reads a `.env` file from the project root and injects its variables into your shell environment. If you previously had a root `.env` file with values like `DB_HOST=database`, `DB_USER=postgres_admin_prod`, or `DB_PASSWORD=\u003cproduction-password\u003e`, these will persist in your shell session and **override** the local `localhost` values in `apps/api/.env.development`.\n\n**Symptoms:**\n- `pnpm --filter api migration:run` fails with `EAI_AGAIN database` (can't resolve Docker hostname)\n- Backend connects to wrong database or uses wrong credentials\n- `password authentication failed` errors despite correct `.env.development`\n\n**Fix:**\n\n```bash\n# 1. Remove the root .env file if it has conflicting vars\nmv .env .env.bak\n\n# 2. Clear the stale variables from your current shell (important!)\nunset DB_HOST DB_PORT DB_USER DB_PASSWORD DB_PASS DB_NAME DB_URL\nunset REDIS_HOST REDIS_PORT REDIS_URL REDIS_PASSWORD\n\n# 3. Verify they're gone — all should be empty\necho $DB_HOST $DB_USER $DB_PASSWORD $REDIS_HOST\n```\n\n\u003e **The bootstrap script no longer creates a root `.env` file** to avoid this issue.\n\n---\n\n### Common Commands Reference\n\n| Command | Description |\n|---------|-------------|\n| `pnpm bootstrap` | One-command first-time setup (deps + env + Docker) |\n| `pnpm dev` | Start all services in development mode |\n| `pnpm build` | Build entire workspace |\n| `pnpm test` | Run all test suites |\n| `pnpm --filter api dev` | Start backend only |\n| `pnpm --filter frontend-web dev` | Start frontend only |\n| `pnpm --filter mobile dev:android` | Sync Capacitor config for dev mode (hot reload) |\n| `pnpm --filter mobile build` | Build webClient + sync APK assets |\n| `pnpm --filter mobile build:android` | Sync + open Android Studio |\n| `pnpm --filter mobile sync` | Sync Capacitor config only |\n| `pnpm --filter api test` | Run backend tests (Jest) |\n| `pnpm --filter frontend-web test` | Run frontend E2E tests (Playwright) |\n| `pnpm --filter api lint` | Lint backend code |\n| `pnpm --filter frontend-web lint` | Lint frontend code |\n| `pnpm --filter api migration:run` | Run pending migrations |\n| `pnpm --filter api migration:create` | Create new DB migration |\n| `pnpm --filter api migration:revert` | Revert last migration |\n\n### Database Migrations\n\nWhen running in Docker (Mode B), migrations run automatically on container start.\n\nWhen developing locally (Mode A), run migrations manually:\n\n```bash\ncd apps/api\n\npnpm run migration:show      # Show migration status\npnpm run migration:generate  # Auto-generate migration from entity changes\npnpm run migration:create    # Create empty migration file\npnpm run migration:run       # Apply pending migrations\npnpm run migration:revert    # Revert the last migration\n```\n\n### Docker Service Management\n\n```bash\n# Start all services\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d\n\n# Start only data services (for local dev)\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d database redis\n\n# View logs\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml logs -f\n\n# Rebuild a single service\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build backend\n\n# Stop everything\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml down\n\n# Reset all data (deletes volumes)\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml down -v\n```\n\n---\n\n---\n\n## 📱 Mobile Development\n\nBudgetGenius runs as a **native Android APK** via [Capacitor 7](https://capacitorjs.com/), which wraps the existing Vite/React web app in a native WebView. This means **100% code reuse** — no rewrite needed.\n\n### How It Works\n\n```\n[React App] → [Vite Build (dist/)] → [Capacitor] → [WebView Nativo] → [APK]\n                    ↓\n              Sin cambios en el código\n```\n\n- The Vite build is output to `apps/webClient/dist/`\n- Capacitor serves these files from the native Android WebView\n- In dev mode (`CAP_DEV=true`), the WebView loads directly from the Vite dev server at `http://10.0.2.2:5173` for **hot reload**\n- Google Login uses a **Strategy Pattern**: `signInWithPopup` / `signInWithRedirect` in web, `@capgo/capacitor-social-login` plugin (Android Credential Manager bottom sheet) in native\n\n### Prerequisites\n\nIn addition to the [base prerequisites](#-getting-started):\n\n- **Java JDK 21** — Required for Android builds ([Adoptium Temurin](https://adoptium.net/temurin/releases/?version=21))\n- **Android Studio** — For the Android SDK, emulator, and APK generation\n- **ANDROID_HOME** env var pointing to your Android SDK (e.g., `/mnt/c/Users/User/AppData/Local/Android/Sdk` for WSL)\n\n### 📱 Mobile App Structure\n\n```\napps/mobile/\n├── package.json           # Capacitor dependencies + build scripts\n├── capacitor.config.ts    # Capacitor configuration (webDir, plugins, server.url)\n├── tsconfig.json          # TypeScript config\n└── android/               # Native Android project (generated by npx cap add android)\n    ├── app/\n    │   └── src/main/assets/  # ← Web assets copied here by cap sync\n    ├── build.gradle\n    └── gradlew            # Gradle wrapper for APK builds\n```\n\n### 🚀 Quick Start: Build \u0026 Run on Emulator\n\n#### Step 1 — Start the Dev Servers\n\n```bash\n# Terminal 1 — Start PostgreSQL + Redis (Docker)\ndocker compose -f docker-compose.yml -f docker-compose.dev.yml up -d database redis\n\n# Terminal 2 — Start Vite + NestJS with hot reload\npnpm dev\n```\n\nVerify both are running:\n| Service | Expected URL |\n|---------|-------------|\n| Vite dev server | `http://localhost:5173/` |\n| NestJS API | `http://127.0.0.1:5000` (HTTP 200 on `/api`) |\n\n#### Step 2 — Sync Capacitor Config for Dev Mode\n\n```bash\ncd apps/mobile\npnpm dev:android  # Sets CAP_DEV=true and runs npx cap sync\n```\n\nThis writes the dev config (`server.url: http://10.0.2.2:5173`) to the Android project so the WebView loads from the Vite dev server.\n\n#### Step 3 — Build \u0026 Install APK\n\n```bash\ncd apps/mobile/android\nexport JAVA_HOME=~/jdk-21.0.5+11   # Or your JDK 21 path\nexport ANDROID_HOME=/path/to/Android/Sdk\n./gradlew assembleDebug\n\n# Install on emulator\nadb install -r app/build/outputs/apk/debug/app-debug.apk\n```\n\n\u003e **💡 Tip:** The first build takes ~3-4 min (Gradle downloads dependencies). Subsequent builds with no dependency changes take ~8s.\n\n#### Step 4 — Open on Emulator\n\nOpen the **BudgetGenius** app in your Android emulator. The app loads from the Vite dev server with **hot reload** — any code change reflects instantly.\n\n### 🔁 Development Cycle (Two Modes)\n\n#### Dev Mode: Hot Reload (Recommended)\n\n| Step | Command | Note |\n|------|---------|------|\n| 1 | `pnpm dev` | Start Vite + NestJS |\n| 2 | `pnpm dev:android` | Sync config (needed once or after config changes) |\n| 3 | Open app on emulator | Hot reload works automatically |\n\n\u003e **One-time setup only:** After `pnpm dev:android` + `adb install`, you only need `pnpm dev` and the emulator. Re-sync is only needed if you change `capacitor.config.ts`.\n\n#### Production Mode: Static APK\n\n```bash\n# Build web assets with production API URL\nexport VITE_API_URL=https://api-budgetgenius.alkiory.com/api\npnpm --filter frontend-web build\n\n# Sync + build APK (CAP_DEV is not set → uses local assets)\ncd apps/mobile\npnpm build \u0026\u0026 cd android\n./gradlew assembleDebug\n```\n\nThis produces a self-contained APK that loads from local assets (no dev server needed).\n\n### 🔌 Google Login Strategy\n\nThe app uses a **Strategy Pattern** that automatically selects the right auth method:\n\n```\ngoogleLogin()\n  → Capacitor.isNativePlatform() = true  →  NativeGoogleLoginStrategy\n  │     → @capgo/capacitor-social-login → signInWithGoogle()\n  │     → idToken → POST /auth/firebase-login\n  │\n  → Capacitor.isNativePlatform() = false →  WebGoogleLoginStrategy\n        → Firebase JS SDK → signInWithPopup()\n        → idToken → POST /auth/firebase-login\n```\n\n- **Web:** Uses `signInWithPopup` / `signInWithRedirect` (Firebase JS SDK) — unchanged from the original behavior\n- **Native:** Uses `@capgo/capacitor-social-login@7` plugin which delegates to Android's Credential Manager — shows an in-app bottom sheet (no Chrome Custom Tab, no deeplink round-trip). The selected Google account's signed `idToken` flows directly to `POST /auth/firebase-login` like the Web SDK path. See `docs/changelog.md` v1.2.0 for the incident postmortem that motivated the swap.\n\n### 🔧 Troubleshooting\n\n#### API calls fail on emulator\n\nEnsure Vite dev server is running on **port 5173**. The APK's Capacitor config points to `http://10.0.2.2:5173` (the emulator's alias for the host). Vite proxies `/api` to `http://localhost:5000/api`.\n\nIf Vite is on a different port, update `capacitor.config.ts`:\n```ts\nserver: { url: 'http://10.0.2.2:\u003cNEW_PORT\u003e', cleartext: true }\n```\nThen re-sync: `pnpm --filter mobile dev:android \u0026\u0026 adb install -r ...`\n\n#### Gradle build fails (JAVA_HOME)\n\nEnsure `JAVA_HOME` points to JDK 21 (not 17, not 11):\n```bash\njava -version  # Must show 21.x\n```\n\n#### Redis not available\n\nIf Redis isn't running, the API starts with a warning and operates without Redis — rate limiting and refresh tokens use safe defaults. To run Redis:\n- **Docker:** `docker compose up -d redis`\n- **Local:** Install Redis and run `redis-server`\n\n#### CORS errors\n\nIf you see CORS errors in the emulator's WebView, make sure the backend's CORS allow-list includes the Capacitor dev server origin. The default dev origins already include `http://10.0.2.2:5173` in `apps/api/src/main.ts`.\n\n---\n\n### GitHub Actions Workflows\n\n| Workflow | Trigger | Actions |\n|----------|---------|---------|\n| **CI/CD** | Push to `main`, PR to `main`/`dev` | Backend: test → build Docker → push to registry → deploy via SSH; Frontend: test |\n| **Playwright** | Push/PR to `main`/`dev` | E2E browser tests |\n| **Firebase Merge** | Push to `main` | Deploy frontend to Firebase Hosting |\n| **Firebase PR** | Pull request | Preview channel deployment |\n\n### Deployment Architecture\n\n- **Frontend:** Vercel (primary) + Firebase Hosting (static assets)\n- **Backend:** Docker container deployed via SSH to VPS\n- **Database:** AWS RDS PostgreSQL (production) / Docker PostgreSQL (development)\n- **Cache:** Redis (Docker in development, managed service in production)\n\n---\n\n## 🧪 Testing\n\n### Backend Tests (Jest)\n\n```bash\n# Unit and integration tests\npnpm --filter api test\n\n# E2E tests\npnpm --filter api test:e2e\n\n# Coverage report\npnpm --filter api test:cov\n```\n\n### Frontend Tests (Playwright)\n\n```bash\n# Run all E2E tests\npnpm --filter frontend-web test\n\n# Run with UI mode\npnpm --filter frontend-web test:ui\n\n# Generate tests via codegen\npnpm --filter frontend-web test:codegen\n\n# CI mode\npnpm --filter frontend-web test:ci\n```\n\n---\n\n## 📐 RPI Development Framework\n\nBudgetGenius integrates the **RPI (Research → Plan → Implement)** framework for structured, AI-assisted development. This framework ensures that all non-trivial changes are properly researched, planned with atomic tasks, and executed with quality gates at every step.\n\n### How It Works\n\n1. **Research Phase** — Analyze the problem, map affected code, gather context → validated with **FAR Scale** (Factual, Actionable, Relevant ≥ 4.00)\n2. **Plan Phase** — Break solution into atomic, single-responsibility tasks → validated with **FACTS Scale** (Feasibility, Atomicity, Clarity, Testability, Size ≥ 3.00)\n3. **Implement Phase** — Execute tasks sequentially with quality gates (Build → Lint → Test) before marking complete\n\nComplete framework documentation is in [`docs/rpi/`](docs/rpi/README.md).\n\n### Quick Start with RPI\n\nTo begin a new feature using RPI, create a directory `rpi/\u003ctask-name\u003e/` and follow the templates in `docs/rpi/`. See [`docs/rpi_instructions.md`](docs/rpi_instructions.md) for exact AI agent prompts.\n\n---\n\n## 📂 Project Structure\n\n```\nBudgetGenius/\n├── apps/\n│   ├── api/                          # NestJS Backend\n│   │   ├── src/\n│   │   │   ├── domain/               # Entities \u0026 Repository Ports\n│   │   │   │   ├── auth/             # Auth entities, repository interface\n│   │   │   │   ├── user/             # User, UserSettings entities\n│   │   │   │   └── dashboard/        # Transaction, Budget, Goal entities\n│   │   │   ├── application/          # Business Logic Services\n│   │   │   │   ├── auth/             # Auth service, DTOs\n│   │   │   │   ├── user/             # User service, seeder\n│   │   │   │   ├── ai/               # OpenAI assistant service\n│   │   │   │   └── dashboard/        # Budget, Goal, Transaction services\n│   │   │   ├── infrastructure/       # Technical Implementation\n│   │   │   │   ├── config/           # Redis, Cookie, JWT strategy, throttling\n│   │   │   │   ├── auth/             # Google OAuth, Firebase middleware\n│   │   │   │   ├── dashboard/        # Dashboard module\n│   │   │   │   ├── user/             # User modules\n│   │   │   │   └── log/              # Winston logger\n│   │   │   ├── adapters/             # Controller \u0026 Repository Implementations\n│   │   │   ├── migrations/           # TypeORM migrations\n│   │   │   └── main.ts               # Application bootstrap\n│   │   ├── test/                     # Jest test files\n│   │   └── Dockerfile\n│   ├── webClient/                    # React Frontend\n│   │   ├── src/\n│   │   │   ├── domain/               # Entity types \u0026 Repository interfaces\n│   │   │   ├── application/          # Auth \u0026 User services\n│   │   │   ├── infrastructure/       # API config, Error boundary, Firebase\n│   │   │   ├── adapters/             # HTTP repositories, Redux store, hooks\n│   │   │   ├── presentation/\n│   │   │   │   ├── pages/            # Page components\n│   │   │   │   ├── components/       # Reusable UI components\n│   │   │   │   ├── layouts/          # Layout components\n│   │   │   │   ├── routes/           # Route config, auth guards\n│   │   │   │   └── utils/            # Routes enum, colors, currency\n│   │   │   └── main.tsx              # Entry point\n│   │   ├── tests/                    # Playwright E2E tests\n│   │   └── dockerfile\n│   └── mobile/                       # Capacitor Native Wrapper\n│       ├── package.json              # Capacitor deps \u0026 scripts\n│       ├── capacitor.config.ts       # Config (webDir, plugins, server.url)\n│       └── android/                  # Native Android project\n├── docs/\n│   ├── rpi/                          # RPI Framework docs\n│   └── rpi_instructions.md           # AI agent prompt guide\n├── scripts/\n│   └── bootstrap.sh                  # Automated setup script\n├── .github/workflows/                # CI/CD pipelines\n├── docker-compose.yml                # Base Docker services\n├── docker-compose.dev.yml            # Development config\n├── docker-compose.prod.yml           # Production config\n├── pnpm-workspace.yaml               # Workspace definition\n└── turbo.json                         # Turbo pipeline\n```\n\n---\n\n## 🔧 Environment Variables\n\n### Backend (`apps/api/.env.development`)\n\n```env\n# Database (localhost for local dev; Docker overrides to 'database' via compose)\nDB_HOST=localhost\nDB_PORT=5432\nDB_USER=postgres_admin_dev\nDB_PASS=dev_password\nDB_NAME=budgetgenius_dev\nDB_URL=postgresql://postgres_admin_dev:dev_password@localhost:5432/budgetgenius_dev\n\n# Server\nPORT=5000\nNODE_ENV=development\nFRONTEND_URL=http://localhost:3001\n\n# JWT (REQUIRED — app won't start without it)\nJWT_SECRET=\u003cgenerate-with-openssl-rand-hex-32\u003e\n\n# Redis (localhost for local dev; Docker overrides to 'redis' via compose)\nREDIS_HOST=localhost\nREDIS_PORT=6379\nREDIS_URL=redis://localhost:6379\n\n# OpenAI (optional — for AI assistant \"Finny\")\nOPENAI_API_KEY=sk-...\n\n# OAuth (optional)\nGOOGLE_CLIENT_ID=\nGOOGLE_CLIENT_SECRET=\n\n# Firebase (optional)\nFIREBASE_PROJECT_ID=\nFIREBASE_PRIVATE_KEY=\nFIREBASE_CLIENT_EMAIL=\nFIREBASE_API_KEY=\nFIREBASE_AUTH_DOMAIN=\n```\n\n\u003e **Note:** When running the backend inside Docker (`docker compose`), `DB_HOST`, `REDIS_HOST`, and `REDIS_URL` are automatically overridden to Docker service names (`database`, `redis`, `redis://redis:6379`) via `docker-compose.dev.yml`. The `.env.development` file always keeps `localhost` values for local `pnpm dev` usage.\n\n### Frontend (`apps/webClient/.env.development`)\n\n```env\nVITE_API_URL=http://localhost:3000/api\nVITE_FRONTEND_URL=http://localhost:3001\n\n# Firebase (optional)\nVITE_FIREBASE_PROJECT_ID=\nVITE_FIREBASE_API_KEY=\nVITE_FIREBASE_AUTH_DOMAIN=\nVITE_FIREBASE_MEASUREMENT_ID=\n```\n\n\u003e **Wave 1 [T1.4] alias note.** Operators who set this var under the older\n\u003e name `VITE_FIREBASE_MEASURENT_ID` (the typo'd spelling historically\n\u003e propagated through this README, `.env.example` and 3 GitHub Actions\n\u003e workflows) — ensure your GitHub Secret is renamed too, otherwise the\n\u003e `firebaseConfig.ts` `measurementId` reads as `undefined` and Analytics\n\u003e silently fails to initialize.\n\n### Complete Reference\n\nSee `.env.example` files in each app directory for the full list of available variables:\n- [`apps/api/.env.example`](apps/api/.env.example)\n- [`apps/webClient/.env.example`](apps/webClient/.env.example)\n\n---\n\n## 📚 API Documentation\n\nWhen the backend is running, Swagger API documentation is available at:\n\n- **Development:** http://localhost:3000/docs\n- **Production:** https://your-domain.com/docs\n\n---\n\n## 🤝 Contributing\n\n### Development Process\n\n1. All non-trivial changes follow the [RPI Framework](#-rpi-development-framework)\n2. Create a feature branch from `dev`\n3. Implement changes with quality gates (Build → Lint → Test)\n4. Submit a PR to `dev`\n5. Use the [Pull Request Template](.github/PULL_REQUEST_TEMPLATE.md)\n\n### Code Conventions\n\n- **Imports:** Use path aliases (`@domain/`, `@application/`, etc.) — never relative paths\n- **Architecture:** Respect layer boundaries — Domain never imports from outer layers\n- **Naming:** kebab-case files, PascalCase classes, camelCase variables\n- **Database:** All tables under `bg_public` schema; always create migrations for schema changes\n\n### For AI Agents\n\nIf you're an AI coding agent working on this project, read the comprehensive [`knowledge.md`](knowledge.md) guide first. It provides the complete context needed to navigate and extend this codebase effectively.\n\n---\n\n## 📄 License\n\nThis project is proprietary and unlicensed. All rights reserved.\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eBudgetGenius\u003c/strong\u003e — Smart money management, powered by AI.\u003cbr\u003e\n  Built with ❤️ by \u003ca href=\"https://github.com/Alkiory\"\u003eAlkiory\u003c/a\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falkiory%2Fbudgetgenius","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falkiory%2Fbudgetgenius","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falkiory%2Fbudgetgenius/lists"}