4.5 KiB
4.5 KiB
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.jsapp 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-DDalign 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
OpenAIdirectly 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
- Scaffold the
Next.jsapp and install core dependencies. - Add the Prisma schema, create the initial SQLite migration, and generate the client.
- Implement CRUD routes and UI forms for expenses and paychecks.
- Implement dashboard aggregation and month filtering.
- Add the AI insight service and persistence for generated monthly insights.
- 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
OpenAImodel 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?