Imported from MTrajK/ai-coding-agents-evaluation (
docs/warm-up-exercises/codex-desktop-gpt-55/expense-tracker/AGENTS.md). Install upstream withnpx skills add MTrajK/ai-coding-agents-evaluation --skill expense-tracker. Copyright stays with the author.
AGENTS.md
Purpose
This file defines the implementation rules, architectural boundaries, and delivery expectations for any AI coding agent working on this repository.
The project is a personal Expense Tracker web application built as a frontend-only React SPA.
The agent should use this file as the primary implementation guide.
1. Product summary
Build a minimal personal expense tracker with:
- no login or registration
- no backend
- no remote API
- a single supported currency: USD
- seeded initial frontend data
- user-created and modified data persisted in browser storage
The application has 3 main pages:
- Dashboard
- Expenses
- Categories
A global Add Expense action must be available from every page.
2. Core product constraints
These constraints are mandatory.
2.1 Functional constraints
- The app is strictly single-user.
- The app is strictly browser-only.
- Do not implement authentication, authorization, profiles, teams, sync, cloud persistence, or backend endpoints.
- Do not introduce multiple currencies.
- All persisted user data must be stored locally in the browser.
- The dashboard is always month-based.
- The app must support light mode and dark mode.
2.2 Technical constraints
Use this stack unless explicitly changed:
- React
- Vite
- TypeScript
- React Router
- Recharts
- TanStack Table
- React Hook Form
- Zod
- localStorage
- React Context +
useReducer - Vitest + React Testing Library
- Playwright
- ESLint + Prettier
- CSS Modules + CSS variables
- date-fns
- lucide-react
Do not introduce unnecessary frameworks or state libraries.
2.3 Explicitly avoid
Do not add:
- backend code
- Redux, Zustand, MobX, or other external state stores
- TanStack Query / SWR
- IndexedDB unless explicitly requested later
- UI frameworks such as Material UI, Ant Design, Chakra, Mantine, etc.
- Tailwind unless explicitly requested later
- server-side rendering
- authentication packages
- i18n/multi-language infrastructure
- overengineered abstractions
3. Product requirements
3.1 Dashboard page
The dashboard is the landing page (/).
Required behavior
- Show month selector controls.
- Support year selection when needed.
- Show two summary cards:
- Total
- Day Average
- Show a pie/donut chart of expense totals by category for the selected month.
- Show a category legend/list under the chart with:
- category color
- category name
- monthly amount
- Hover interaction must be synchronized between chart and legend.
Hover behavior
When hovering a chart segment:
- that segment becomes visually emphasized
- other segments become visually subdued
- tooltip shows category name and amount
- matching legend item becomes active
When hovering a legend item:
- matching chart segment becomes active
- other chart segments become visually subdued
- hovered legend item becomes emphasized
Month switching behavior
When switching month/year:
- dashboard chart data updates
- category totals update
- total updates
- day average updates
3.2 Expenses page
The expenses page route is /expenses.
Required table columns
Each row must show:
- expense name
- category
- date
- amount
- edit action
- delete action
Required filters
Above the table, provide filtering by:
- name (text input)
- category (dropdown)
- amount range (
from,to) - date range (
from,to)
Pagination requirements
Support:
- previous / next
- page size options: 10, 25, 50
Delete behavior
When delete is clicked:
- show confirmation dialog: Delete the expense?
- actions:
- Yes
- No
- clicking Yes removes the expense
Edit behavior
When edit is clicked:
- open the shared expense modal
- prepopulate fields
- saving updates the existing expense
3.3 Categories page
The categories page route is /categories.
Required behavior
- Show all categories as pills.
- Provide one input field and one Add button.
- Added categories appear immediately in the pills list.
- Each pill must contain a delete
Xaction.
Add button rules
- The button is enabled only when the current input is valid.
- Category name must be unique.
- Category name should be trimmed.
- After successful add:
- category is added
- input is cleared
- button becomes disabled again
Delete category behavior
If a category is not used by any expense:
- show confirmation dialog: Delete the category?
- actions:
- Yes
- No
If a category is used by at least one expense:
- show blocking dialog: The category can not be deleted, it's used by at least one expense.
- action:
- Ok
This business rule must be enforced in logic, not only visually.
3.4 Add expense modal
A floating Add Expense button must exist on all 3 pages.
When clicked, open a modal with fields:
- Name — text input, required
- Category — dropdown, optional
- Amount — number input, required
- Date — date input, optional, defaults to today
Modal actions:
- Save
- Cancel
3.5 Edit expense modal
Use the same modal and same form as the Add Expense flow.
Differences:
- fields are prepopulated
- submit action updates existing record instead of creating one
3.6 Navbar
The navbar must be visible across all pages.
Required behavior
- It should provide navigation to the 3 pages.
- Use icons for:
- dashboard / pie
- expenses / table
- categories / settings-style icon
- Active page must be highlighted.
- Include light/dark mode toggle on the right side.
4. Architecture requirements
Follow a feature-based architecture.
Target structure
src/
app/
features/
dashboard/
expenses/
categories/
expense-form/
theme/
domain/
storage/
shared/
styles/
Architectural rules
- Keep page components thin.
- Keep business logic outside JSX-heavy components.
- Keep calculations in selectors/utilities.
- Keep persistence behind repository-style storage helpers.
- Keep feature-specific code inside feature folders.
- Put only truly reusable UI primitives into
shared/.
5. Routing rules
Use React Router.
Routes
/→ Dashboard/expenses→ Expenses/categories→ Categories
Routing guidance
- Use a central layout wrapper.
- Navbar must persist across route changes.
- Floating Add Expense button must persist across route changes.
- Shared expense modal may be mounted at layout level.
6. State management rules
Use React Context + useReducer for shared application state.
Global state should include
- expenses
- categories
- selected dashboard month
- selected dashboard year
- theme mode
- add/edit expense modal state
Local state should include
- active hovered chart category
- page-local dialog state
- form-internal transient state
- local filter UI state when not globally needed
Action naming
Use namespaced action names, for example:
expense/addexpense/updateexpense/deletecategory/addcategory/deletedashboard/setMonthdashboard/setYeartheme/setexpenseModal/openCreateexpenseModal/openEditexpenseModal/close
Do not use vague action names.
7. Data model rules
Use explicit TypeScript interfaces/types.
Expense
interface Expense {
id: string;
name: string;
categoryId: string | null;
amount: number;
date: string;
createdAt: string;
updatedAt: string;
}
Category
interface Category {
id: string;
name: string;
color: string;
createdAt: string;
}
Important modeling rule
Expenses should reference categories by category ID, not by category name string.
8. Persistence rules
Use localStorage only.
Persistence requirements
- Seed initial data from frontend constants/files.
- On first app launch, initialize storage from seed data.
- After initialization, load from storage.
- Persist state changes to storage.
Storage rules
- Do not call
localStoragedirectly from page components. - Create storage/repository modules such as:
expensesRepository.tscategoriesRepository.tsthemeRepository.tsseed.tsmigrations.ts(optional but allowed)
Suggested keys
expense-tracker.expensesexpense-tracker.categoriesexpense-tracker.themeexpense-tracker.version
9. Forms and validation
Use React Hook Form + Zod.
Expense form rules
- name is required
- name is trimmed
- amount is required
- amount must be greater than zero
- category is optional
- date defaults to today if empty
Category form rules
- category name is required
- category name is trimmed
- category name must be unique
Validation architecture rules
- Validation must be schema-driven.
- Do not scatter validation logic across components.
- Keep schemas in feature-level
schemas/folders.
10. Dashboard logic rules
The dashboard must use derived selector logic.
Required selectors/utilities
Examples:
- select expenses for selected month/year
- group monthly expenses by category
- compute monthly total
- compute average-per-day
- derive chart input data
- derive available years
Important rule
Do not compute all dashboard logic inline in the page component.
11. Expenses table rules
Use TanStack Table for table state/modeling.
Table requirements
- semantic table rendering
- filtering support
- pagination support
- predictable row mapping
Important rule
Do not place all table filtering/pagination logic directly inside the page component.
Encapsulate it in feature hooks, selectors, or table helpers.
12. Styling rules
Use:
- CSS Modules
- CSS variables
- theme tokens
Styling constraints
- Keep styles modular.
- Use CSS variables for theme colors and design tokens.
- Use root theme attribute such as
data-theme="light"/data-theme="dark". - Keep UI consistent across pages.
- Prefer simple, clean, modern UI.
- Avoid overdesigned or animation-heavy solutions.
Theme rules
- On first load, system preference may be used as default.
- Manual user toggle must override and persist.
- Theme preference must be stored in browser storage.
13. UX requirements
The app should feel simple, fast, and deterministic.
Required UX states
Support explicit UI for:
- empty expenses list
- empty category list
- no dashboard data for selected month
- invalid form input
- delete confirmations
- blocked category deletion
Interaction quality rules
- destructive actions must require confirmation
- disabled buttons must reflect invalid input states
- forms should have clear labels
- active navigation state must be visually obvious
- chart and legend hover state must feel synchronized
14. Accessibility rules
Minimum accessibility expectations:
- use semantic HTML where appropriate
- form controls must have labels
- icon buttons must have accessible names
- dialogs/modals must support focus management
- keyboard interaction must work for critical flows
- color must not be the only meaning indicator when possible
Do not ignore accessibility because the app is small.
15. Testing requirements
Testing is mandatory.
15.1 Unit tests
Write unit tests for:
- reducer actions
- selectors
- dashboard calculations
- filter logic
- category deletion rules
- storage helpers when practical
- validation schemas when practical
15.2 Component tests
Write component tests for:
- expense modal
- category add form
- delete confirmation dialogs
- navbar navigation state
- theme toggle
- expenses filter bar
15.3 E2E tests
Write Playwright tests for critical flows:
- navigate between pages
- add expense
- edit expense
- delete expense
- add category
- block deletion of used category
- switch dashboard month and verify updates
- persist data after reload
- persist theme after reload
Definition of done for a feature
A feature is not complete unless:
- implementation works
- types are correct
- tests are added or updated
- lint passes
- formatting passes
- behavior matches product rules in this file
16. Code quality rules
TypeScript
- prefer explicit, strong typing
- avoid
any - avoid unsafe casts unless necessary and justified
- keep domain types centralized and consistent
React
- prefer small focused components
- avoid large monolithic page files
- avoid deep prop drilling when context is appropriate
- keep side effects isolated and intentional
Naming
- components:
PascalCase.tsx - hooks:
useSomething.ts - utilities:
camelCase.ts - schemas:
somethingSchema.ts - reducers:
somethingReducer.ts
General
- do not leave dead code
- do not leave placeholder TODO blocks without reason
- do not add speculative abstractions for future features
- prefer readable code over clever code
17. Recommended implementation order
Implement in this sequence unless task scope requires otherwise:
- project bootstrap and base configuration
- routing and layout shell
- domain types and seed data
- storage repositories
- reducer and context provider
- navbar and theme toggle
- dashboard selectors and dashboard UI
- categories page and category deletion rules
- shared expense modal and form validation
- expenses table, filters, pagination, edit/delete flows
- test coverage and UX polish
18. Agent working rules
When making changes:
- Understand the current folder structure before adding files.
- Follow the feature-based architecture already defined.
- Reuse existing components and utilities when appropriate.
- Do not introduce new dependencies unless they are clearly justified.
- Keep changes scoped to the task.
- Prefer deterministic implementations over clever shortcuts.
- Preserve consistency in naming, file placement, and patterns.
- When a business rule exists in this file, treat it as authoritative.
When uncertain
Prefer:
- simpler design
- fewer dependencies
- stronger typing
- reusable pure logic
- explicit tests
Do not invent product features that are not requested.
19. Non-goals
These are out of scope unless explicitly requested later:
- income tracking
- recurring expenses
- export/import
- charts other than the dashboard pie/donut chart
- analytics beyond the described dashboard
- budgets
- notifications
- multi-device sync
- offline-first advanced caching
- user accounts
- backend integration
20. Final instruction
The correct implementation is not the one with the most abstractions or packages.
The correct implementation is the one that:
- satisfies the product requirements exactly
- respects the chosen tech stack
- follows the architecture
- remains readable and maintainable
- is well-tested
- stays minimal