Luca Ledger is a client-side personal finance manager built with React, Vite, and Material UI. It keeps checking, savings, and credit card accounts in sync, encrypts all sensitive data in the browser, and deploys as a static site on GitHub Pages—no backend required.
- Multi-account coverage: Track deposits, withdrawals, and statement cycles across checking, savings, and credit cards.
- Client-side encryption: AES-256-GCM with PBKDF2-derived keys keeps data local and secure in IndexedDB via Dexie.
- Session-aware auth: Password-derived keys gate every session; there is no password recovery, by design.
- Rich UI + insights: Material-UI, D3/Recharts visualizations, and Redux selectors provide responsive charts and ledgers.
- Offline-first: All logic runs locally, so the app works even without a network connection after first load.
- React 18.2 with hooks and context
- Vite 4.x for dev/prod builds
- Material UI 5.x + Emotion for theming
- Redux Toolkit for state + encrypted middleware
- Dexie (IndexedDB) for encrypted persistence
- Day.js/Date-fns and D3/Recharts for date math and charts
- Vitest + Testing Library + jsdom for tests
- Password → PBKDF2 (100k iterations, SHA-256) → Key Wrapping Key (KWK)
- KWK unwraps a Data Encryption Key (DEK)
- Each record is encrypted with AES-256-GCM + unique IV before storage in IndexedDB
- Session tokens (3 days) store wrapped DEKs; exports remain unencrypted and must be protected manually
See ENCRYPTION.md and src/crypto/ for implementation details.
- Auth states:
loading,no-users,login,authenticated,legacy-migration - Users authenticate via username + password; legacy plaintext data migrates automatically
- Sessions live in
sessionStorageand expire after 72 hours
- React Router (
/dashboard,/accounts,/ledger,/categories,/settings,/help,/) drives navigation src/components/MainLayoutrenders global navigation + version banner- Redux slices live under
src/store/*(accounts, transactions, categories, statements, encryption)
src/
├── components/ # UI modules (auth, ledger, analytics, layout, modals)
├── views/ # Route-level pages (Dashboard, Accounts, Ledger, etc.)
├── store/ # Redux Toolkit slices, encrypted middleware, selectors
├── auth/ # Auth context + provider
├── crypto/ # AES/PBKDF2 helpers and key manager
├── validation/ # Zod/AJV schemas + validation helpers
├── hooks/ # Custom React hooks (balances, statements, etc.)
└── __tests__/ # Vitest suites, fixtures, utilities
- Node.js 20+
- Yarn 1.22 (classic)
git clone https://github.com/LucaFinancial/LucaLedger.git
cd LucaLedger
yarn install # ~40 seconds; do not interrupt| Command | Purpose | Notes |
|---|---|---|
yarn dev |
Start Vite dev server (http://localhost:5173) | Hot reload + fast refresh |
yarn build |
Production build to dist/ |
~15 s; copies CNAME + 404 on GH Pages build |
yarn preview |
Serve built assets locally | Useful for final QA |
yarn lint |
ESLint with React/A11y rules | Required before pushing |
yarn test |
Vitest suite (headless) | Use yarn test:watch while developing |
Run these steps after significant UI changes:
- Navigate between Dashboard (
/dashboard) and Accounts (/accounts) - Create an account via "Create New Account" button and verify form validation
- Confirm Material-UI components render responsively on mobile + desktop widths
- Ensure the header shows the semantic app version (format
vX.Y.Z) and the update dialog dismisses
- Unit + integration tests live under
src/__tests__/ - Use
yarn test:coveragefor v8 instrumentation reports - Fake IndexedDB + jsdom handle crypto + Dexie flows in tests
- ESLint + Prettier rules enforce single quotes, 2 spaces,
@/import aliases, and a11y checks
Luca Ledger follows Semantic Versioning (MAJOR.MINOR.PATCH) with RC suffixes during issue development.
- Determine bump type
- Major: breaking schema or removal of features
- Minor: new features, UX enhancements, noticeable perf gains
- Patch: bug fixes, refactors, docs, dependency bumps
- Apply RC suffix while iterating
- First commit on an issue:
npm version <major|minor|patch> --preid=rc --no-git-tag-version→ results inX.Y.Z-rc.1 - Increment RC number on subsequent commits (
-rc.2,-rc.3, ...)
- First commit on an issue:
- Final release
- Drop
-rc.*, runnpm version <type> - Ensure
package.jsonversion matches header display (src/components/VersionDisplay)
- Drop
- Production builds are deployed via GitHub Actions to GitHub Pages at https://lucaledger.app/
yarn build:pageshandles the static-site artifacts (CNAME,404.html)yarn deployusesgh-pagesto publish thedist/directory manually if needed
- Build hangs? Wait the full 15 seconds; do not cancel.
- Dev server fails? Ensure dependencies are installed and no other process uses port 5173.
- Lint errors? Run
yarn lintfor actionable rule hints; most issues are autofixable. - Encryption data loss? Passwords cannot be recovered. Export data regularly and store encrypted backups externally.
- Fork and branch from
main - Follow the versioning flow above and include RC bumps in commits
- Add or update tests + docs for every change
- Link issues in PR descriptions using
Closes #<id>so GitHub auto-closes them
MIT © LucaFinancial