This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
npm run dev # Start Vite dev server on port 4000
npm run build # Production build
npm run preview # Preview production build
npm test # Jest unit tests
npm run cypress:open # Cypress E2E UI
npm run cypress:run # Cypress E2E headless
npm run docs # Generate TypeDoc docsPARITY is a privacy-first, local-first dual-currency personal finance PWA for multi-currency economies (primarily Venezuela — USD/VES/EUR). Built with React 19 + Vite 6 + TypeScript.
All app state lives in a single AppContent component in App.tsx — no Redux or Zustand. State is passed down via props. Key state domains:
- Entities:
accounts,transactions,scheduledPayments,budgets,goals,shoppingLists - Rates:
exchangeRate,usdRateParallel,euroRate,euroRateParallel(fetched fromve.dolarapi.com) - Multi-profile:
profiles,activeProfileId,userProfile - UI:
currentView,isDevMode,displayCurrency,isBalanceVisible,navbarFavorites
All data is encrypted at rest using Web Crypto API (AES-GCM + PBKDF2). services/crypto.ts handles key derivation, encryption, and decryption.
- Primary store: IndexedDB via
services/db.ts. Object store"app_data"holds all entities. - Fallback:
localStoragekeyparity_data_v3for legacy/encrypted blob. - UI preferences (not encrypted):
displayCurrency,isBalanceVisible,isDevMode,activeProfileId,navbarFavorites,autoLockEnabled,autoLockDelay,biometricsEnabled,app_theme.
Offline sync: services/sync.ts queues mutations when offline and processes them on reconnect. Google Drive backup is optional (dev-mode feature) via useGoogleDriveSync hook; exports/imports use the same encrypted format.
currentView in AppContent controls which view renders. Views live in /views/. Key views:
Dashboard— Widget-based overview with draggable/reorderable widget grid (widgetRegistry.tsx)AddTransaction/TransferView— Custom numeric keypad, smart category detectionBudgetView,AnalysisView,GoalView— Planning/forecasting featuresFiscalReportView— Tax-tagged transactions summaryCurrencyPerformanceView— Exchange rate history with dev-mode parallel rate cardOnboarding— First-run setup; Google Drive import shown only inisDevMode
isDevMode is toggled by clicking the version label 10 times rapidly (handleDevModeTrigger in App.tsx). It persists in localStorage key isDevMode. Dev mode unlocks: Google Drive sync UI, parallel exchange rate selector in settings, parallel rate card in CurrencyPerformanceView.
Custom modular translation system — no third-party library. Files in /i18n/{en,es,pt}/ split by domain (common, views, categories, alerts, fiscal, misc). Usage: getTranslation(userProfile.language, key). Falls back to English then to the key string. Language is per-profile.
Defined in types.ts:
Currency:USD | VES | EUR | USDTTransactionType:EXPENSE | INCOME | TRANSFERRateType:'OFFICIAL' | 'PARALLEL'FiscalTag:'TAXABLE_INCOME' | 'DEDUCTIBLE_EXPENSE' | 'NEUTRAL'ViewState: union of 16 view name stringsTransaction: includesamountInOriginalCurrency,normalizedAmount(USD),exchangeRateAtTime,fiscalTag,profileIdUserProfile: includeslanguage,rateType,hideDevMode,dashboardTxLimit,hideWelcome,hideName
utils/forecast.ts: Linear regression, month-end projections, budget pace alerts, fiscal year summaries, runway calculations.utils/formatUtils.ts:formatAmount()/formatSecondaryAmount()— always pass active exchange rate andrateType.constants.tsx: 31+ spending categories with Lucide icons/colors;SMART_CATEGORIES_ENmap for auto-categorization by merchant name; recurring payment templates.themes.json: 3 built-in themes (Original Dark, Midnight Ocean, Forest) — CSS variables applied byuseTheme.
Required in .env:
VITE_GOOGLE_CLIENT_ID=
VITE_APP_ENCRYPTION_SECRET=
VITE_APP_ENCRYPTION_SALT=