## Context The repository starts with a product plan and OpenSpec configuration but no application code. The first version needs a complete local-first implementation using `Next.js`, `Prisma`, `SQLite`, and `OpenAI`, while keeping scope intentionally narrow: one user, manual data entry, fixed categories, and dashboard-only insights. Month boundaries are based on the local machine timezone, which affects date parsing, monthly aggregation, and paycheck coverage calculations. ## Goals / Non-Goals **Goals:** - Build a single deployable `Next.js` app with UI views and server routes in one codebase. - Persist expenses, paychecks, and generated monthly insights in a local SQLite database managed by Prisma. - Centralize monthly aggregation logic so dashboard reads and AI generation use the same numbers. - Keep AI integration isolated behind a small service layer that prepares structured monthly context and calls `OpenAI`. - Make v1 testable with deterministic validation, aggregation, and safe fallback behavior for sparse data. **Non-Goals:** - Authentication, multi-user support, bank sync, receipt scanning, background jobs, or email delivery. - Automatic categorization, editing data through AI, or free-form custom categories in v1. - Complex financial forecasting beyond simple next-month guidance derived from recent activity. ## Decisions ### Use a single `Next.js` app for UI and APIs - Rationale: the project is small, local-first, and benefits from one codebase for pages, route handlers, and shared utilities. - Alternative considered: separate frontend and API service. Rejected because it adds deployment and data-sharing complexity without helping the v1 scope. ### Use Prisma with SQLite for persistence - Rationale: Prisma provides schema management, typed queries, and straightforward migrations while keeping SQLite as a simple embedded database. - Alternative considered: raw SQLite queries. Rejected because it slows down schema evolution and validation during initial development. ### Store money as integer cents and dates as local calendar strings - Rationale: integer cents avoid floating-point issues, and local-date strings such as `YYYY-MM-DD` align with the local machine timezone requirement for monthly boundaries. - Alternative considered: floating-point amounts or UTC timestamps only. Rejected because both introduce avoidable ambiguity for monthly reporting. ### Put aggregation logic in shared server-side services - Rationale: dashboard totals, paycheck coverage, category breakdowns, and AI snapshots must stay consistent across endpoints. - Alternative considered: separate logic per route. Rejected because it risks drift between dashboard and insight generation. ### Add an AI service boundary with structured prompt input and fallback responses - Rationale: the app needs provider isolation, predictable prompt shape, and safe messaging when data is too sparse for useful advice. - Alternative considered: calling `OpenAI` directly from a route handler with raw records. Rejected because it couples prompting, aggregation, and transport too tightly. ## Risks / Trade-offs - [Local timezone handling differs by machine] -> Normalize month calculations around stored local-date strings and test month edges explicitly. - [SQLite limits concurrency] -> Acceptable for single-user local-first v1; no mitigation beyond keeping writes simple. - [AI output quality varies with sparse or noisy data] -> Add minimum-data fallback logic and keep prompts grounded in structured aggregates. - [OpenAI dependency requires API key management] -> Read configuration from environment variables and keep failure messages explicit in the UI/API. ## Migration Plan 1. Scaffold the `Next.js` app and install core dependencies. 2. Add the Prisma schema, create the initial SQLite migration, and generate the client. 3. Implement CRUD routes and UI forms for expenses and paychecks. 4. Implement dashboard aggregation and month filtering. 5. Add the AI insight service and persistence for generated monthly insights. 6. Run automated tests, then exercise the main flows in the browser. Rollback is straightforward in early development: revert the code change and reset the local SQLite database if schema changes become invalid. ## Open Questions - Which `OpenAI` model should be the initial default for monthly insight generation? - Should generated monthly insights overwrite prior insights for the same month or create a historical trail of regenerated summaries? - Do we want soft confirmation in the UI before deleting expenses or paychecks, or is immediate deletion acceptable for v1?