{"id":49410485,"url":"https://github.com/nrajesh/vaulted.money","last_synced_at":"2026-04-29T00:01:40.157Z","repository":{"id":317058610,"uuid":"1051228744","full_name":"nrajesh/vaulted.money","owner":"nrajesh","description":"A privacy-focused, local-first personal finance app. Track spending, manage budgets, and gain insights - without sending your data to the cloud.","archived":false,"fork":false,"pushed_at":"2026-04-26T20:18:25.000Z","size":37250,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-26T21:23:23.569Z","etag":null,"topics":["account-tracking","budget","cashflow","dexiejs","electron","expense-tracker","expenses","local-first","money","money-manager","nlp-search","no-tracking","open-source","personal-finance","privacy-focused","react","spending-tracker","typescript","vault","vaulted"],"latest_commit_sha":null,"homepage":"https://vaulted.money","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nrajesh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","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":"2025-09-05T16:36:46.000Z","updated_at":"2026-04-26T20:21:03.000Z","dependencies_parsed_at":"2025-09-28T18:00:41.717Z","dependency_job_id":null,"html_url":"https://github.com/nrajesh/vaulted.money","commit_stats":null,"previous_names":["nrajesh/budget-it","nrajesh/vaulted.money"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/nrajesh/vaulted.money","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nrajesh%2Fvaulted.money","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nrajesh%2Fvaulted.money/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nrajesh%2Fvaulted.money/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nrajesh%2Fvaulted.money/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nrajesh","download_url":"https://codeload.github.com/nrajesh/vaulted.money/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nrajesh%2Fvaulted.money/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32404340,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-28T19:38:08.556Z","status":"ssl_error","status_checked_at":"2026-04-28T19:37:55.688Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["account-tracking","budget","cashflow","dexiejs","electron","expense-tracker","expenses","local-first","money","money-manager","nlp-search","no-tracking","open-source","personal-finance","privacy-focused","react","spending-tracker","typescript","vault","vaulted"],"created_at":"2026-04-29T00:01:20.354Z","updated_at":"2026-04-29T00:01:37.116Z","avatar_url":"https://github.com/nrajesh.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Vaulted Money - Secure Finance Tracker\n\n_A privacy-focused, local-first Secure Finance app. Track spending, manage budgets, and gain insights - without sending your data to the cloud._\n\n[![CircleCI Build](https://img.shields.io/circleci/build/github/nrajesh/vaulted.money/main?logo=circleci\u0026style=for-the-badge\u0026token=CCIPRJ_Vr8m8ZBprdRweVA3p3Zuf1_ec111876745b6b9fe207e3e3bbbfbbf28de994d9)](https://app.circleci.com/pipelines/github/nrajesh/vaulted.money)\n[![GitHub](https://img.shields.io/badge/GitHub-Repository-181717?style=for-the-badge\u0026logo=github\u0026logoColor=white)](https://github.com/nrajesh/vaulted.money)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://opensource.org/licenses/MIT)\n\n![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?style=for-the-badge\u0026logo=typescript\u0026logoColor=white)\n![React](https://img.shields.io/badge/React-20232A?style=for-the-badge\u0026logo=react\u0026logoColor=61DAFB)\n![Vite](https://img.shields.io/badge/Vite-646CFF?style=for-the-badge\u0026logo=vite\u0026logoColor=white)\n![Electron](https://img.shields.io/badge/Electron-191970?style=for-the-badge\u0026logo=electron\u0026logoColor=white)\n![TailwindCSS](https://img.shields.io/badge/Tailwind_CSS-38B2AC?style=for-the-badge\u0026logo=tailwind-css\u0026logoColor=white)\n![Google Gemini](https://img.shields.io/badge/Google%20Gemini-8E75B2?style=for-the-badge\u0026logo=google%20gemini\u0026logoColor=white)\n\n---\n\n**Motivation:** Vaulted Money exists because basic budgeting should not sit behind paywalls when the core idea is simple math and honest records - and because your data should stay yours. For the full story, local-first ethos, and visuals, see **[Why Vaulted Money exists](documentation/WHY_VAULTED_MONEY.md)**.\n\n---\n\n## 🌟 Key Features\n\n| Category                | Feature                                                                                                                                 |\n| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |\n| 🔒 **Privacy**          | 100% local - data lives in your browser's IndexedDB. No cloud, no servers.                                                              |\n| 📚 **Multi-Ledger**     | Separate ledgers for Personal, Business, Joint finances.                                                                                |\n| 💳 **Transactions**     | Track with categories, sub-categories, vendors, and account groups.                                                                     |\n| 📊 **Budgets**          | Monthly, quarterly, yearly, or one-time budgets with progress tracking.                                                                 |\n| 🔁 **Scheduled**        | Recurring transactions with smart deduplication on import.                                                                              |\n| 📈 **Analytics**        | Visual breakdowns of income, expenses, and savings trends.                                                                              |\n| 🫀 **Financial Pulse**  | Premium dashboard for high-level financial health monitoring.                                                                           |\n| 💬 **Smart Search**     | Natural language filtering for transactions, categories, and dates.                                                                     |\n| 🤖 **Optional AI**      | BYOK (Bring Your Own Key) for auto-categorizing transactions using OpenAI, Gemini, Anthropic, Mistral, Perplexity, or Custom endpoints. |\n| 💾 **Backup \u0026 Restore** | Encrypted or plain JSON backups - import instantly without page reloads.                                                                |\n| ⏰ **Auto-Backup**      | Scheduled backups via File System Access API (web) or direct filesystem (Electron).                                                     |\n\n---\n\n## 🏗️ System Architecture\n\nFor a detailed view of the system architecture, including web and desktop component diagrams, data flow sequences, and technical decisions, please refer to the [**Architecture Documentation**](documentation/ARCHITECTURE.md).\n\n---\n\n## 🏠 Public Homepage (`/`)\n\nThe root route (`/`) is a public landing page that runs without an active ledger. It covers the privacy-first / local-first / open-source positioning, a ledger workspace preview, backup and CSV-import guidance, and copy-paste install commands. The authenticated app lives under `/ledgers`.\n\n\u003e The homepage is implemented in `src/pages/HomePage.tsx` and is kept outside the authenticated `Layout` route so it never triggers the active-ledger redirect.\n\n---\n\n## 🚀 Getting Started\n\n### Prerequisites\n\n\u003e [!IMPORTANT]\n\u003e Before you begin, make sure you have the following installed:\n\n| Requirement | Version | How to Install                                          |\n| ----------- | ------- | ------------------------------------------------------- |\n| **Node.js** | v18+    | [Download](https://nodejs.org/) or use `nvm install 18` |\n| **pnpm**    | v8+     | `npm install -g pnpm`                                   |\n| **Git**     | Any     | [Download](https://git-scm.com/)                        |\n\n\u003e [!NOTE]\n\u003e **pnpm** is strongly recommended. The project uses `pnpm-lock.yaml`, and all scripts are configured for it.\n\n### Step-by-Step Setup\n\n```bash\n# 1. Clone the repository\ngit clone https://github.com/nrajesh/vaulted.money.git\ncd vaulted.money\n\n# 2. Install dependencies\npnpm install\n\n# 3. Verify the setup (optional but recommended)\npnpm lint \u0026\u0026 pnpm build\n```\n\n\u003e [!TIP]\n\u003e If `pnpm install` fails, try deleting `node_modules` and running `pnpm install` again:\n\u003e\n\u003e ```bash\n\u003e rm -rf node_modules \u0026\u0026 pnpm install\n\u003e ```\n\n---\n\n### 🌐 Running the Web App\n\n```bash\npnpm dev\n```\n\nOpen **http://localhost:8081** in your browser or the port defined in vite.config.ts. That's it!\n\n---\n\n### 🖥️ Running the Electron Desktop App\n\n```bash\npnpm run electron:dev\n```\n\nThis single command does everything:\n\n1. Starts the Vite dev server on port `8081`\n2. Waits for the server to be ready (`wait-on`)\n3. Compiles Electron main \u0026 preload TypeScript\n4. Launches the Electron window\n\n\u003e [!WARNING]\n\u003e **Do NOT run `pnpm dev` separately before `electron:dev`.**\n\u003e The `electron:dev` script already starts Vite internally using `concurrently`. Running them separately will cause a port conflict on `8081`.\n\n\u003e [!NOTE]\n\u003e **First-time Electron run** may take longer as it compiles TypeScript files and downloads the Electron binary (~100 MB).\n\n---\n\n### 📱 Mobile Support\n\n| Platform          | Supported? | How                                         |\n| ----------------- | ---------- | ------------------------------------------- |\n| **macOS**         | ✅         | Electron desktop app or browser             |\n| **Windows**       | ✅         | Electron desktop app or browser             |\n| **Linux**         | ✅         | Electron desktop app or browser             |\n| **iOS / Android** | ✅ Native  | Run natively via Capacitor (`npx cap sync`) |\n\n\u003e Electron cannot run on mobile devices. For mobile access, either host the web version or build the native apps using the provided Capactior iOS/Android targets for local continuity features.\n\n### Build Paths\n\nUse these command sets depending on what you are trying to produce:\n\n| Goal | What it builds | Command(s) |\n| --- | --- | --- |\n| Web only | Production web bundle in `dist/` | `pnpm build` |\n| Web only (local preview) | Production web bundle plus local preview server | `pnpm build` then `pnpm preview` |\n| Electron only | Electron desktop packages using the current web bundle | `pnpm run electron:build` |\n| Electron dev | Local desktop app with live Vite dev server | `pnpm run electron:dev` |\n| Mobile only (shared sync) | Rebuild web assets and sync both native Capacitor projects | `pnpm run mobile:refresh` |\n| Android only | Rebuild web assets, sync Android, assemble debug APK | `pnpm run android:build:apk` |\n| Android release APK | Rebuild web assets, sync Android, assemble release APK | `pnpm run android:build:apk:release` |\n| iOS simulator only | Rebuild web assets, sync iOS, build simulator app | `pnpm run ios:build:simulator` |\n| Full local release sweep | Electron package + Android debug APK + iOS simulator build | `pnpm run release:local` |\n\nNotes:\n- Electron packaging always depends on a fresh web build because the renderer ships from `dist/`.\n- Capacitor mobile builds always depend on a fresh web build because `cap sync` copies `dist/` into the native shells.\n- `pnpm run mobile:sync` is a lower-level helper that rebuilds the web app and runs `cap sync` without opening, uninstalling, or producing native binaries.\n\n### Mobile Refresh and Clean Reinstall\n\nUse the shared refresh script whenever web assets, native icons, or Capacitor configuration change:\n\n```bash\npnpm run mobile:refresh\n```\n\nThat script runs:\n\n```bash\npnpm run build\npnpm exec cap sync ios\npnpm exec cap sync android\n```\n\nFor a full clean reinstall on each simulator/emulator after syncing:\n\n```bash\n# iOS\nxcrun simctl uninstall booted com.vaultedmoney.app || true\npnpm exec cap open ios\n```\n\nThen in Xcode:\n1. `Product \u003e Clean Build Folder`\n2. `Product \u003e Run`\n\n```bash\n# Android\nadb uninstall com.vaultedmoney.app || true\ncd android\n./gradlew clean\npnpm exec cap open android\n```\n\nThen in Android Studio:\n1. let Gradle sync\n2. run the `app` target again\n\n\u003e Use the clean reinstall flow after icon updates. Both iOS and Android aggressively cache launcher assets, so `cap sync` alone is not always enough to surface the latest icon.\n\n---\n\n### 🔨 Building for Production\n\n| Target                  | Command                        | Output                                                          |\n| ----------------------- | ------------------------------ | --------------------------------------------------------------- |\n| Web                     | `pnpm build`                   | `dist/`                                                         |\n| Desktop (all platforms) | `pnpm run electron:build`      | `release/` (DMG, EXE, AppImage)                                 |\n| Mobile sync only        | `pnpm run mobile:sync`         | Rebuilds web assets and syncs Capacitor without native compile  |\n| Shared mobile refresh   | `pnpm run mobile:refresh`      | Rebuilds web assets and syncs both Capacitor targets            |\n| Android APK             | `pnpm run android:build:apk`   | `android/app/build/outputs/apk/debug/`                          |\n| Android release APK     | `pnpm run android:build:apk:release` | `android/app/build/outputs/apk/release/`                  |\n| iOS simulator app       | `pnpm run ios:build:simulator` | `ios/build/DerivedData/Build/Products/Release-iphonesimulator/` |\n| Full local release sweep| `pnpm run release:local`       | Electron package + Android debug APK + iOS simulator build      |\n\n### GitHub Release Assets\n\nPublishing a GitHub release now keeps GitHub's default source ZIP/TAR assets and also uploads:\n\n- macOS Electron DMG\n- Android release APK\n- unsigned iOS simulator app ZIP\n\nThe iOS artifact is a simulator build. Producing a device-installable IPA requires Apple signing certificates and provisioning profiles, which should be provided as repository secrets before enabling an IPA export step.\n\nFor local Android testing, `pnpm run android:build:apk` builds the debug APK, which is already signed by Gradle and installable with `adb`.\n\n---\n\n## 🔗 Live Demo\n\nDeploy a production build to your host (for example [Cloudflare Pages](https://pages.cloudflare.com/)) and use that URL as the public demo.\n\n---\n\n## 📂 Project Structure\n\n```\nvaulted.money/\n├── electron/                  # Electron-specific code\n│   ├── main.ts                #   Main process (window, IPC, fs access)\n│   └── preload.ts             #   Preload script (contextBridge)\n├── src/\n│   ├── components/            # Reusable UI components\n│   │   ├── ui/                #   Shadcn primitives (Button, Dialog, etc.)\n│   │   ├── budgets/           #   Budget management\n│   │   ├── charts/            #   Visualizations\n│   │   ├── dashboard/         #   Home dashboard widgets\n│   │   ├── dialogs/           #   Modals and popups\n│   │   ├── filters/           #   Search \u0026 filtering logic\n│   │   └── transactions/      #   Transaction tables \u0026 logic\n│   ├── contexts/              # React Context Definitions\n│   ├── providers/             # Context Providers (Data, Theme, etc.)\n│   ├── hooks/                 # Custom React hooks\n│   ├── pages/                 # Route-level page components\n│   │   ├── HomePage.tsx       #   Public landing page (route: /)\n│   │   └── ...                #   Authenticated app pages\n│   ├── types/                 # TypeScript type definitions\n│   ├── utils/                 # Helper functions (currency, date, etc.)\n│   └── tests/                 # Test files\n├── .agent/workflows/          # AI agent slash command definitions\n├── scheduled-agents/          # AI agent rulesets (personality \u0026 rules)\n├── specs/                     # Feature specifications (Speckit artifacts)\n├── .circleci/                 # CircleCI Pipeline config\n├── package.json\n├── vite.config.ts\n└── tsconfig.json\n```\n\n---\n\n## ✅ Quality Assurance\n\nWe enforce high code quality standards using a strict **CircleCI** pipeline. Every pull request must pass the following checks before merging:\n\n| Check          | Command              | Description                                             |\n| -------------- | -------------------- | ------------------------------------------------------- |\n| **Linting**    | `pnpm lint`          | ESLint checks for code quality and best practices.      |\n| **Type Safe**  | `tsc --noEmit`       | Full TypeScript strict mode check.                      |\n| **Formatting** | `pnpm format:check`  | Prettier verification to ensure consistent style.       |\n| **Testing**    | `pnpm test:coverage` | Vitest unit tests with coverage reporting.              |\n| **Security**   | `pnpm audit`         | Checks dependencies for known vulnerabilities.          |\n| **Build**      | `pnpm build`         | Verifies that the production bundle compiles correctly. |\n\n\u003e [!TIP]\n\u003e You can run `pnpm validate` locally to run TypeScript and ESLint checks in one go.\n\n\u003e [!NOTE]\n\u003e **Security Overrides**: `package.json` includes a handful of `pnpm.overrides` that pin transitive dependencies (`tar`, `undici`, `flatted`, `yauzl`, `dompurify`, `@tootallnate/once`, `picomatch`) to patched versions. These resolve Dependabot alerts for packages we don't import directly - they're pulled in by tooling like Vitest, ESLint, Capacitor CLI, and Electron. Run `pnpm audit` to verify.\n\n---\n\n## 📚 Documentation \u0026 Workflow\n\n### 1. Interpreting the Documentation Folder\n\nThe `documentation/` folder serves as the \"Constitution\" and \"Operating System\" for the project.\n\n| File                                                                         | Purpose                                                                                                             |\n| ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |\n| **[`DESIGN.md`](documentation/DESIGN.md)**                                   | **Brand Identity Manual**. Philosophy, logo geometry, and color strategies for light/dark modes.                    |\n| **[`WHY_VAULTED_MONEY.md`](documentation/WHY_VAULTED_MONEY.md)**             | **Why this project**. Motivation, privacy stance, hopes for forks/localization, and story infographics.             |\n| **[`SPEC_DRIVEN_DEVELOPMENT.md`](documentation/SPEC_DRIVEN_DEVELOPMENT.md)** | **The Workflow Guide**. Comprehensive guide on how to build features using the Spec-Driven Development methodology. |\n| **[`AGENTS.md`](documentation/AGENTS.md)**                                   | **The Rulebook**. Technical constraints and boundaries for the AI agent (e.g., \"Privacy First\", \"Use Tailwind\").    |\n| **[`SUPPORT.md`](documentation/SUPPORT.md)**                                 | **Support Policy**. How to get help and file issues.                                                                |\n| **[`SECURITY.md`](documentation/SECURITY.md)**                               | **Security Policy**. Reporting vulnerabilities and privacy details.                                                 |\n\n### 2. How to Work with Speckit\n\n\u003e **Note**: For a deep dive into the workflow, read the [**Spec-Driven Development Guide**](documentation/SPEC_DRIVEN_DEVELOPMENT.md).\n\n#### Quick Start\n\n1.  **Specify**: `/speckit.specify \"Build a new feature\"`\n2.  **Plan**: `/speckit.plan`\n3.  **Task**: `/speckit.tasks`\n4.  **Implement**: `/speckit.implement`\n\n### 3. AI Agent Workflows\n\nThis project includes three specialized AI agents that can be invoked via slash commands in a compatible AI-powered IDE. Each agent focuses on a specific area of code quality and runs a self-contained workflow: it scans the codebase, identifies improvements, implements changes, and verifies them - all from a single command.\n\n| Command           | Agent       | What It Does                                                                                                                             |\n| ----------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |\n| `/agent.palette`  | 🎨 Palette  | Finds and fixes **UX and accessibility** issues - missing ARIA labels, poor color contrast, keyboard navigation gaps, and visual polish. |\n| `/agent.bolt`     | ⚡ Bolt     | Finds and fixes **performance** issues - unnecessary re-renders, missing memoization, bundle size optimizations, and slow queries.       |\n| `/agent.sentinel` | 🛡️ Sentinel | Finds and fixes **security** issues - XSS vulnerabilities, unsafe data handling, missing input validation, and dependency risks.         |\n\n#### How do they work?\n\nEach agent has two parts:\n\n1. **Ruleset** (`scheduled-agents/*.md`) - A detailed personality and checklist that tells the agent what to look for and how to behave. Think of it as the agent's \"mission brief\".\n2. **Workflow** (`.agent/workflows/agent.*.md`) - The step-by-step process the agent follows: create a branch → scan the codebase → implement fixes → run all quality checks → merge.\n\n#### Do I need a specific IDE?\n\nThe slash commands (e.g., `/agent.palette`) work automatically in IDEs that support the `.agent/workflows/` convention. Even if your IDE doesn't support slash commands, the ruleset files in `scheduled-agents/` are plain markdown - you can read them and follow the instructions manually, or paste them as context for any AI assistant.\n\n---\n\n## 🛠️ Development Guide\n\n### AI Provider Configuration\n\nVaulted Money supports \"Bring Your Own Key\" (BYOK) AI categorization. You can manage AI providers directly in the application.\n\n1.  **AI Provider Management**: Navigate to **Management \u003e AI Providers** in the sidebar.\n2.  **Add/Edit Provider**:\n    - Click **Add AI Provider** to add a new endpoint.\n    - Set the **Name**, **Model ID**, and **Base URL**.\n    - **Provider Type**: Choose Gemini, OpenAI, Anthropic, Mistral, Perplexity, or Custom (OpenAI compatible).\n3.  **Configure API Key**: Go to **Settings**, select your new provider as the default, and enter your API key. Keys are stored safely and locally in your browser's IndexedDB.\n4.  **Local LLMs**: Add a provider with Type `Custom` and Base URL `http://localhost:11434/v1` (for Ollama) to use local models securely without any internet access required.\n\n\u003e [!NOTE]\n\u003e AI providers are stored in the database and included in exports, but **API keys are never exported** for security reasons. You must re-enter keys on new devices.\n\n### ⚠️ Important: Content Security Policy (CSP)\n\nBecause Vaulted Money is a strict local-first application, its Content Security Policy (CSP) blocks outgoing network requests by default.\n\n**If you add a completely new API domain via the UI (e.g. `https://api.my-new-ai.com`), you MUST add it to the allowed domains list in the code.**\n\n1. Open `vite.config.ts`.\n2. Add your new domain to the `aiDomains` array:\n\n```typescript\n// vite.config.ts\nconst aiDomains = [\n  \"https://generativelanguage.googleapis.com\",\n  \"https://api.openai.com\",\n  \"https://api.anthropic.com\",\n  \"https://api.mistral.ai\",\n  \"https://api.perplexity.ai\",\n  // Add your new domain here:\n  \"https://api.your-custom-ai-provider.com\",\n];\n```\n\n3. Restart the development server (`pnpm dev`) or rebuild the app.\n\n\u003e [!TIP]\n\u003e You rarely need to write new code to support a new AI provider! Simply select `Custom` as the Provider Type in the UI. Our robust JSON parser handles OpenAI-compatible JSON responses automatically. You only need to edit `useAutoCategorize.ts` if the new provider has a completely unique request structure (like Anthropic).\n\n### Adding New Components\n\n1. `src/components/ui/` - Generic, reusable UI primitives\n2. `src/components/\u003cfeature\u003e/` - Feature-specific components\n3. `src/components/layout/` - Layout wrappers\n\n**Guidelines:**\n\n- Use **functional components** with TypeScript interfaces\n- Style with **Tailwind CSS** utility classes\n- Ensure **responsive design** (mobile-first)\n- Add JSDoc comments for complex logic\n\n### State Management\n\n- `useTransactions()` - global financial data\n- `useState` - UI-only state (dialog open/close)\n- `useQuery` - async data fetching with TanStack Query\n\n### Testing\n\n```bash\npnpm test              # Run unit tests (Vitest)\npnpm test:coverage     # Run with coverage report\npnpm lint              # Run ESLint checks\npnpm validate          # TypeScript + ESLint in one shot\n```\n\n---\n\n## 📦 Deployment\n\nThe web build is a static SPA (`dist/`). Use any static host; **Cloudflare Pages** is a good fit: connect the Git repository, set the build command to `pnpm run build`, the build output directory to `dist`, and use Node 20+ to match local builds. The `public/_redirects` file is included for client-side routing on Cloudflare Pages.\n\nYou can also deploy the `dist` folder with `npx wrangler pages deploy dist` (Wrangler from devDependencies or `npx`) after `pnpm run build`, if you are not using Git-integrated builds.\n\n---\n\n## 🛡️ Privacy Note\n\n\u003e This application runs entirely in your browser (or local Electron instance). **No data is ever sent to a server** unless you explicitly configure and trigger the completely optional AI auto-categorization feature using your own API key. Clearing your browser cache or site data will remove your financial data unless you have exported a backup. Always keep backups of your important data.\n\n---\n\n\u003cp align=\"center\"\u003e\n  Made with ❤️ for your financial freedom\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnrajesh%2Fvaulted.money","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnrajesh%2Fvaulted.money","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnrajesh%2Fvaulted.money/lists"}