commit 5d7e25c01505b0115bb0b5c469d33d42da224cce Author: Vijayakanth Manoharan Date: Mon Mar 23 12:10:18 2026 -0400 Define OpenSpec change for monthly expense tracker v1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..95075e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.next/ +node_modules/ +.env +.env.local +prisma/dev.db +prisma/dev.db-journal +.opencode/ +.claude/ +.codex/ diff --git a/openspec/changes/monthly-expense-tracker-v1/.openspec.yaml b/openspec/changes/monthly-expense-tracker-v1/.openspec.yaml new file mode 100644 index 0000000..0a32546 --- /dev/null +++ b/openspec/changes/monthly-expense-tracker-v1/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-03-23 diff --git a/openspec/changes/monthly-expense-tracker-v1/design.md b/openspec/changes/monthly-expense-tracker-v1/design.md new file mode 100644 index 0000000..7830457 --- /dev/null +++ b/openspec/changes/monthly-expense-tracker-v1/design.md @@ -0,0 +1,63 @@ +## 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? diff --git a/openspec/changes/monthly-expense-tracker-v1/proposal.md b/openspec/changes/monthly-expense-tracker-v1/proposal.md new file mode 100644 index 0000000..81e0f06 --- /dev/null +++ b/openspec/changes/monthly-expense-tracker-v1/proposal.md @@ -0,0 +1,28 @@ +## Why + +The project currently has a product plan but no runnable application, spec artifacts, or implementation scaffold. Formalizing the first version now creates a clear contract for building a local-first expense tracker with reliable monthly summaries and AI-generated guidance. + +## What Changes + +- Add a local-first web app for tracking expenses and biweekly paychecks without authentication. +- Add dashboard capabilities for month-to-date totals, category breakdowns, cash flow, and spending comparisons. +- Add manual AI insight generation for a selected month using structured aggregates and transaction samples. +- Add local persistence, validation, and API routes for expenses, paychecks, dashboard data, and insight generation. + +## Capabilities + +### New Capabilities +- `expense-tracking`: Record, list, and delete categorized expenses for a given date. +- `paycheck-tracking`: Record, list, and delete paycheck entries based on actual pay dates. +- `monthly-dashboard`: View month-specific spending, income, and derived financial summaries. +- `monthly-insights`: Generate read-only AI insights from monthly financial activity. + +### Modified Capabilities +- None. + +## Impact + +- Affected code: new `Next.js` application, server routes, UI views, Prisma schema, and AI integration service. +- APIs: `POST/GET/DELETE` routes for expenses and paychecks, `GET /dashboard`, and `POST /insights/generate`. +- Dependencies: `Next.js`, `Prisma`, `SQLite`, and `OpenAI` SDK. +- Systems: local machine timezone handling for month boundaries and persisted local database storage. diff --git a/openspec/changes/monthly-expense-tracker-v1/specs/expense-tracking/spec.md b/openspec/changes/monthly-expense-tracker-v1/specs/expense-tracking/spec.md new file mode 100644 index 0000000..d265e0d --- /dev/null +++ b/openspec/changes/monthly-expense-tracker-v1/specs/expense-tracking/spec.md @@ -0,0 +1,23 @@ +## ADDED Requirements + +### Requirement: User can record categorized expenses +The system SHALL allow the user to create an expense with a title, amount, category, and local calendar date using fixed starter categories. + +#### Scenario: Valid expense is created +- **WHEN** the user submits a title, positive amount, valid category, and valid local date +- **THEN** the system stores the expense and returns the created record + +#### Scenario: Invalid expense is rejected +- **WHEN** the user submits a missing title, invalid amount, invalid category, or invalid date +- **THEN** the system rejects the request with a validation error and does not store the expense + +### Requirement: User can review and delete expenses +The system SHALL allow the user to list recorded expenses and delete a specific expense by identifier. + +#### Scenario: Expenses are listed +- **WHEN** the user requests expenses for the app +- **THEN** the system returns stored expenses in a stable order with their recorded fields + +#### Scenario: Expense is deleted +- **WHEN** the user deletes an existing expense +- **THEN** the system removes that expense and it no longer appears in future listings or aggregates diff --git a/openspec/changes/monthly-expense-tracker-v1/specs/monthly-dashboard/spec.md b/openspec/changes/monthly-expense-tracker-v1/specs/monthly-dashboard/spec.md new file mode 100644 index 0000000..ebf7d7c --- /dev/null +++ b/openspec/changes/monthly-expense-tracker-v1/specs/monthly-dashboard/spec.md @@ -0,0 +1,23 @@ +## ADDED Requirements + +### Requirement: Dashboard shows month-specific financial totals +The system SHALL return month-specific dashboard data for a requested `YYYY-MM` month using the local machine timezone for month boundaries. + +#### Scenario: Dashboard totals are calculated for a populated month +- **WHEN** the user requests the dashboard for a month with expenses and paychecks +- **THEN** the system returns total expenses, total paychecks, net cash flow, and a category breakdown for that month + +#### Scenario: Dashboard supports partial current-month data +- **WHEN** the user requests the dashboard for the current month before the month is complete +- **THEN** the system returns meaningful month-to-date totals and comparisons using the transactions recorded so far + +### Requirement: Dashboard includes derived spending comparisons +The system SHALL provide derived comparisons for the selected month, including highest category, largest expense, average daily spend, and paycheck coverage information. + +#### Scenario: Derived comparisons are available +- **WHEN** the selected month contains enough data for comparisons +- **THEN** the system returns the highest category, largest single expense, average daily spend, and spend-versus-paycheck coverage values + +#### Scenario: Derived comparisons degrade safely for sparse data +- **WHEN** the selected month has no expenses or otherwise insufficient data for a comparison +- **THEN** the system returns null or empty-safe comparison fields instead of failing diff --git a/openspec/changes/monthly-expense-tracker-v1/specs/monthly-insights/spec.md b/openspec/changes/monthly-expense-tracker-v1/specs/monthly-insights/spec.md new file mode 100644 index 0000000..fa2291f --- /dev/null +++ b/openspec/changes/monthly-expense-tracker-v1/specs/monthly-insights/spec.md @@ -0,0 +1,23 @@ +## ADDED Requirements + +### Requirement: User can generate monthly AI insights on demand +The system SHALL allow the user to manually generate AI insights for any month with existing or sparse data by sending structured monthly context to the configured `OpenAI` provider. + +#### Scenario: Insights are generated for a month with data +- **WHEN** the user requests insight generation for a month with recorded activity +- **THEN** the system sends monthly aggregates plus transaction samples to the AI service and returns a rendered narrative summary with structured supporting totals + +#### Scenario: Prior month insights can be generated +- **WHEN** the user requests insight generation for a previous month that has recorded data +- **THEN** the system generates and stores insight output for that requested month + +### Requirement: Insight generation is read-only and safe for sparse months +The system SHALL keep AI insight generation read-only and return a safe fallback summary when a month does not have enough data for meaningful guidance. + +#### Scenario: Sparse month returns fallback insight +- **WHEN** the user requests insight generation for a month with empty or near-empty data +- **THEN** the system returns a fallback message instead of low-confidence advice + +#### Scenario: AI does not mutate financial records +- **WHEN** the system generates or stores monthly insights +- **THEN** no expense or paycheck records are created, updated, or deleted as part of that request diff --git a/openspec/changes/monthly-expense-tracker-v1/specs/paycheck-tracking/spec.md b/openspec/changes/monthly-expense-tracker-v1/specs/paycheck-tracking/spec.md new file mode 100644 index 0000000..c54731f --- /dev/null +++ b/openspec/changes/monthly-expense-tracker-v1/specs/paycheck-tracking/spec.md @@ -0,0 +1,23 @@ +## ADDED Requirements + +### Requirement: User can record paychecks by pay date +The system SHALL allow the user to create a paycheck with a positive amount and a local pay date. + +#### Scenario: Valid paycheck is created +- **WHEN** the user submits a positive amount and valid local pay date +- **THEN** the system stores the paycheck and returns the created record + +#### Scenario: Invalid paycheck is rejected +- **WHEN** the user submits a missing or invalid amount or date +- **THEN** the system rejects the request with a validation error and does not store the paycheck + +### Requirement: User can review and delete paychecks +The system SHALL allow the user to list recorded paychecks and delete a specific paycheck by identifier. + +#### Scenario: Paychecks are listed +- **WHEN** the user requests paychecks for the app +- **THEN** the system returns stored paychecks in a stable order with their recorded fields + +#### Scenario: Paycheck is deleted +- **WHEN** the user deletes an existing paycheck +- **THEN** the system removes that paycheck and it no longer appears in future dashboard totals or insight inputs diff --git a/openspec/changes/monthly-expense-tracker-v1/tasks.md b/openspec/changes/monthly-expense-tracker-v1/tasks.md new file mode 100644 index 0000000..18899ff --- /dev/null +++ b/openspec/changes/monthly-expense-tracker-v1/tasks.md @@ -0,0 +1,31 @@ +## 1. Project setup + +- [ ] 1.1 Scaffold the `Next.js` app with TypeScript, linting, and baseline project configuration. +- [ ] 1.2 Add runtime dependencies for Prisma, SQLite, validation, charts, and `OpenAI` integration. +- [ ] 1.3 Add development dependencies and scripts for testing, Prisma generation, and local development. +- [ ] 1.4 Add base environment and ignore-file setup for local database and API key configuration. + +## 2. Persistence and shared services + +- [ ] 2.1 Define Prisma models for `Expense`, `Paycheck`, and `MonthlyInsight` and create the initial SQLite migration. +- [ ] 2.2 Implement shared validation schemas for expenses, paychecks, and month query parameters. +- [ ] 2.3 Implement shared money and local-date utilities for month boundary calculations. + +## 3. Expense and paycheck workflows + +- [ ] 3.1 Implement expense API routes for create, list, and delete operations. +- [ ] 3.2 Implement paycheck API routes for create, list, and delete operations. +- [ ] 3.3 Build the `Add Expense` view with form submission, validation feedback, and expense listing. +- [ ] 3.4 Build the `Income/Paychecks` view with form submission, validation feedback, and paycheck listing. + +## 4. Dashboard and insights + +- [ ] 4.1 Implement monthly dashboard aggregation services for totals, category breakdowns, and derived comparisons. +- [ ] 4.2 Implement the dashboard API route and render dashboard sections for month-to-date metrics and comparisons. +- [ ] 4.3 Implement the `OpenAI` insight service with structured monthly snapshot input and sparse-month fallback logic. +- [ ] 4.4 Implement insight generation and display in the dashboard, including persisted monthly insight records. + +## 5. Verification + +- [ ] 5.1 Add automated tests for validation, persistence, dashboard aggregates, and insight fallback behavior. +- [ ] 5.2 Verify the primary user flows in the browser, including expense entry, paycheck entry, dashboard updates, and insight generation. diff --git a/openspec/config.yaml b/openspec/config.yaml new file mode 100644 index 0000000..392946c --- /dev/null +++ b/openspec/config.yaml @@ -0,0 +1,20 @@ +schema: spec-driven + +# Project context (optional) +# This is shown to AI when creating artifacts. +# Add your tech stack, conventions, style guides, domain knowledge, etc. +# Example: +# context: | +# Tech stack: TypeScript, React, Node.js +# We use conventional commits +# Domain: e-commerce platform + +# Per-artifact rules (optional) +# Add custom rules for specific artifacts. +# Example: +# rules: +# proposal: +# - Keep proposals under 500 words +# - Always include a "Non-goals" section +# tasks: +# - Break tasks into chunks of max 2 hours diff --git a/plan.md b/plan.md new file mode 100644 index 0000000..76af33a --- /dev/null +++ b/plan.md @@ -0,0 +1,81 @@ +# Monthly Expense Tracker With AI Insights + +## Summary +Build a single-user, local-first web app for manually recording daily expenses and biweekly paychecks, then generating month-to-date and end-of-month spending insights with next-month guidance. + +The first version is optimized for fast daily entry and a dashboard-first review flow. It uses fixed starter categories, a simple local database, and an in-app AI summary rather than email or exports. + +## Implementation Changes +- App shape: + - Build a web app with 3 primary views: `Dashboard`, `Add Expense`, and `Income/Paychecks`. + - Keep it single-user and local-first with no authentication in v1. +- Core data model: + - `Expense`: `id`, `date`, `title`, `amount`, `category`, `createdAt`. + - `Paycheck`: `id`, `payDate`, `amount`, `createdAt`. + - `MonthlyInsight`: `id`, `month`, `year`, `generatedAt`, `summary`, `recommendations`, `inputSnapshot`. +- Categories: + - Ship with fixed starter categories such as `Rent`, `Food`, `Transport`, `Bills`, `Shopping`, `Health`, `Entertainment`, `Misc`. + - Store category as a controlled value so monthly summaries can group reliably. +- Dashboard behavior: + - Show current month totals for expenses, category breakdown, paycheck total, and net cash flow. + - Include month-to-date charts and simple comparisons like highest category, largest single expense, average daily spend, and spend vs paycheck coverage. + - Provide a `Generate Insights` action that works any time during the month, not only at month-end. +- AI insight generation: + - Build a summarization pipeline that prepares structured monthly aggregates plus recent transaction samples, then sends that context to the AI model. + - Ask the model to return: + - spending pattern summary + - unusual categories or spikes + - paycheck-to-spend timing observations + - practical next-month suggestions + - Keep AI read-only in v1: it does not edit data or auto-categorize entries. +- Storage and architecture: + - Use a simple embedded database for local-first persistence, preferably SQLite. + - Implement the app with `Next.js` for the web UI and server routes. + - Use `Prisma` for the data layer and migrations. + - Keep the AI integration behind a small service boundary so the model/provider can be swapped later without changing UI code. + - Use `OpenAI` for insight generation in v1. +- Public interfaces / APIs: + - `POST /expenses`, `GET /expenses`, `DELETE /expenses/:id` + - `POST /paychecks`, `GET /paychecks`, `DELETE /paychecks/:id` + - `GET /dashboard?month=YYYY-MM` + - `POST /insights/generate?month=YYYY-MM` + - Insight response should include structured fields for totals and a rendered narrative summary for the dashboard. + +## Implementation Checklist +- [ ] Scaffold the `Next.js` app and set up base project config. +- [ ] Add `Prisma` with a SQLite database and define `Expense`, `Paycheck`, and `MonthlyInsight` models. +- [ ] Build shared validation and month/date helpers using local machine time. +- [ ] Implement expense CRUD routes and forms. +- [ ] Implement paycheck CRUD routes and forms. +- [ ] Build dashboard aggregation logic for totals, categories, cash flow, and comparisons. +- [ ] Add the insight generation service boundary and `OpenAI` integration. +- [ ] Render AI insight output in the dashboard with fallback behavior for sparse months. +- [ ] Add tests for validation, aggregates, persistence, and insight generation. +- [ ] Verify all month-boundary behavior using local timezone dates. + +## Test Plan +- Expense entry: + - Create valid expense with title, amount, date, and category. + - Reject missing or invalid amount/date/category. +- Paycheck tracking: + - Record multiple biweekly paychecks in one month and across month boundaries. + - Verify dashboard cash-flow totals use actual paycheck dates, not monthly averaging. +- Dashboard calculations: + - Category totals, monthly totals, average daily spend, and net cash flow are correct. + - Current-month partial data still renders meaningful month-to-date views. +- Insight generation: + - AI request uses aggregated monthly inputs plus transaction samples. + - Manual generation works for current month and prior months with existing data. + - Empty or near-empty months return a safe fallback message instead of low-quality advice. +- Persistence: + - Data remains available after app restart. + - Deleting an expense or paycheck updates dashboard and future insight results correctly. + +## Assumptions And Defaults +- First version is for your own use only, with no login or multi-user support. +- Expense entry is fully manual; receipt scanning and bank sync are out of scope. +- AI insights appear only inside the dashboard. +- The app supports month-to-date previews as well as end-of-month review. +- Fixed starter categories are sufficient for v1; custom categories can be added later. +- Income is modeled as discrete biweekly paychecks because that materially affects next-month guidance and intra-month cash-flow interpretation. +- Month and paycheck boundaries use the local machine timezone.