Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 8 additions & 51 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,12 @@
# Contributing To OpenLedger
# Contributing to OpenLedger

Thanks for considering a contribution. OpenLedger is intentionally small, calm, and privacy-first. Changes should make the app more trustworthy, understandable, and maintainable without turning it into a bank-connected growth product.
Please see [docs/Contributing.md](docs/Contributing.md) for the full contributing guide.

## Local Setup
## Quick Links

```bash
git clone https://github.com/sparshsam/openledger.git
cd openledger
npm install
npm run dev
```
- [Development Setup](docs/Development.md)
- [Architecture](docs/Architecture.md)
- [Deployment](docs/Deployment.md)
- [Testing](docs/Testing.md)

Open `http://localhost:3000`.

## Required Checks

Run these before opening a pull request:

```bash
npm run lint
npm run typecheck
npm run build
```

For UI changes, also check:

- Desktop around `1440x1000`
- Mobile around `390x900`
- CSV import preview
- Manual transaction form
- Account management
- JSON export/import

## Product Principles

- No bank login unless it is optional and clearly separated from local mode.
- No shame language, gamification, or manipulative finance copy.
- Prefer clear data ownership over convenience.
- Keep privacy limitations explicit.
- Keep the interface quiet and legible.

## Pull Requests

Please include:

- What changed
- Why it changed
- Validation performed
- Screenshots for visual changes
- Known limitations or follow-up work

## License

By contributing, you agree that your contributions are provided under the project's AGPL-3.0-or-later license.
By contributing, you agree that your contributions will be licensed under AGPLv3.
234 changes: 154 additions & 80 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,109 +1,183 @@
# OpenLedger
<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="assets/branding/icon-source.png">
<img src="assets/branding/icon-source.png" width="96" height="96" alt="OpenLedger">
</picture>
<h1 align="center">OpenLedger</h1>
<p align="center">
<strong>A private, local-first personal finance ledger.</strong>
<br />
No bank connections, no dashboards, no noise. Your financial data stays on your device.
</p>
<br />
</div>

**A private, local-first personal finance ledger. No bank connections, no dashboards, no noise.**
<p align="center">
<img src="assets/hero/dashboard-desktop.png" width="100%" alt="OpenLedger Dashboard" style="border-radius: 12px; max-width: 1000px;">
</p>

[![Live app](https://img.shields.io/badge/live-ledger.kovina.org-7A2F00?style=flat-square)](https://ledger.kovina.org)
[![CI](https://img.shields.io/github/actions/workflow/status/sparshsam/openledger/ci.yml?branch=main&style=flat-square&label=ci)](https://github.com/sparshsam/openledger/actions/workflows/ci.yml)
[![License: AGPL v3](https://img.shields.io/badge/license-AGPL--3.0--or--later-6f7d61?style=flat-square)](LICENSE)
[![Next.js](https://img.shields.io/badge/Next.js-16-black?style=flat-square)](https://nextjs.org)
[![TypeScript](https://img.shields.io/badge/TypeScript-5-3178c6?style=flat-square)](https://www.typescriptlang.org)
<br />

OpenLedger is a calm, local-first finance tool for everyday budgeting and records. It runs entirely in the browser — your financial data stays on your device unless you choose to back it up.
<div align="center">

**Live app:** [https://ledger.kovina.org](https://ledger.kovina.org)
[![Website](https://img.shields.io/badge/website-ledger.kovina.org-7A2F00?style=for-the-badge&logo=vercel)](https://ledger.kovina.org)
[![Latest Release](https://img.shields.io/github/v/release/sparshsam/openledger?sort=semver&style=for-the-badge&label=Release&color=2563eb)](https://github.com/sparshsam/openledger/releases)
[![Source Code](https://img.shields.io/badge/Source%20Code-GitHub-181717?style=for-the-badge&logo=github&logoColor=white)](https://github.com/sparshsam/openledger)

![OpenLedger dashboard](assets/screenshot-main.png)
</div>

## Quick Links
<br />

| Link | Description |
| --- | --- |
| [Live app](https://ledger.kovina.org) | Production deployment on Vercel |
| [Architecture docs](docs/architecture.md) | Data model, auth, and sync architecture |
| [Security policy](SECURITY.md) | Reporting guidance and current limitations |
| [Contributing](CONTRIBUTING.md) | Local setup and contribution expectations |
| [Changelog](CHANGELOG.md) | Notable project changes |
| [License](LICENSE) | AGPL-3.0-or-later |
---

## Gallery

<p align="center">
<img src="assets/gallery/screenshot-main.png" width="49%" alt="Ledger Dashboard" style="border-radius: 8px;">
<img src="assets/gallery/dashboard-mobile.png" width="30%" alt="Mobile View" style="border-radius: 8px;">
<br /><br />
<img src="assets/gallery/screenshot-search.png" width="49%" alt="Transactions View" style="border-radius: 8px;">
</p>

<br />

---

## Why OpenLedger

Most finance tools want to connect to your bank, analyze your spending, and sell you insights. OpenLedger does none of that.

**It's a ledger — not a dashboard.** Enter transactions manually. Track accounts, budgets, and goals. Your data lives in your browser. Cloud backup is optional and opt-in. No analytics, no telemetry, no third-party data collection. No bank credentials or Plaid connections.

<br />

---

## Features

- **Accounts** — Create checking, credit, savings, and loan accounts. Every transaction belongs to an account.
- **Transactions** — Manual entry with edit, duplicate, delete. Search, filter by date/account/category/type, sortable columns.
- **CSV Import** — Import bank statement CSV/TSV files with column mapping, preview, duplicate detection, and account selection.
- **Budgets** — Monthly spending plans with progress tracking and over-budget warnings.
- **Goals** — Savings milestones with target amounts, progress tracking, and contribution support.
- **Recurring Entries** — Schedule-based recurring transaction engine with upcoming entry preview.
- **Receipt Capture** — Photo upload from camera or gallery, stored in Supabase Storage.
- **Cloud Sync** — Signed-in users can manually back up and restore their ledger to Supabase.
- **Search** — Global search across all transactions with Quick Jump keyboard navigation.
- **Guest Mode** — Full local functionality without signing in. No account required.
- **MCP Server** — AI agents (Claude Code, Cursor, etc.) can read/write your data via the Model Context Protocol.
- **PWA** — Installable as a standalone app with service worker caching.

## Tech Stack

| Layer | Technology |
|-------|-----------|
| Framework | Next.js 16 (App Router) |
| Language | TypeScript 5 |
| Styling | Tailwind CSS 4 + custom CSS |
| State | React hooks + `localStorage` persistence |
| Auth | Supabase Auth (Google OAuth) |
| Cloud | Supabase Postgres (Elora project, `openledger_` prefix) |
| Crash Reporting | Sentry (optional) |
| Hosting | Vercel → [ledger.kovina.org](https://ledger.kovina.org) |
| License | AGPL-3.0-or-later |

## Screenshots

| Ledger dashboard | Transactions view |
<div align="center">

| | |
|---|---|
| ![Overview](assets/screenshot-main.png) | ![Transactions](assets/screenshot-search.png) |
| **Accounts** — Checking, credit, savings, loan. Every transaction belongs to an account. | **Transactions** — Manual entry, edit, duplicate, delete. Search, filter, sort. |
| **CSV Import** — Bank statement CSV/TSV import with column mapping, preview, dedup. | **Budgets** — Monthly spending plans with progress tracking and over-budget warnings. |
| **Goals** — Savings milestones with target amounts and progress tracking. | **Recurring Entries** — Schedule-based recurring transaction engine with preview. |
| **Receipt Capture** — Photo upload from camera or gallery to Supabase Storage. | **Guest Mode** — Full local functionality without signing in. No account required. |
| **Cloud Sync** — Manual backup and restore to Supabase (opt-in). | **Search** — Global search with Quick Jump keyboard navigation. |
| **MCP Server** — AI agents can read/write your data via Model Context Protocol. | **PWA** — Installable as a standalone app with offline caching. |

</div>

<br />

---

## Designed For

**People who want a calm, honest view of their finances — no algorithms, no upsells.**

- **Budget-conscious individuals** tracking everyday spending against monthly plans
- **Freelancers** keeping simple income/expense records
- **Anyone tired of apps that try to sell them something while they check their balance

<br />

## Privacy
---

OpenLedger is **local-first by design**:
## Design Philosophy

- All data stays in your browser's `localStorage` by default.
- CSV parsing happens locally — no data is uploaded to a server.
- Cloud backup is **opt-in** — only triggered manually by signed-in users.
- No analytics, no telemetry, no third-party data collection.
- No bank credentials or Plaid connections.
> _"A calm finance tool — quiet, capable, private."_

> **Important:** `localStorage` is convenient but not encrypted secure storage. Export JSON backups regularly and store them somewhere you control.
No dashboards. No charts begging for attention. No push notifications. Local-first by design — your data lives in your browser unless you choose to back it up. Clean typography, generous spacing, dark-mode first. Every screen has one job.

## Local Development
<br />

```bash
git clone https://github.com/sparshsam/openledger.git
cd openledger
npm install
npm run dev
```
---

Open [http://localhost:3000](http://localhost:3000). The app works fully without any environment variables.
## Built With

### Optional: Supabase auth + cloud backup
<p align="center">
<img src="https://img.shields.io/badge/Next.js-16-black?style=for-the-badge&logo=next.js" alt="Next.js 16">
<img src="https://img.shields.io/badge/TypeScript-5.x-3178c6?style=for-the-badge&logo=typescript" alt="TypeScript">
<img src="https://img.shields.io/badge/Tailwind%20CSS-4-06B6D4?style=for-the-badge&logo=tailwindcss" alt="Tailwind CSS 4">
<img src="https://img.shields.io/badge/Supabase-optional-3fcf8e?style=for-the-badge&logo=supabase" alt="Supabase">
<img src="https://img.shields.io/badge/Vercel-deployed-black?style=for-the-badge&logo=vercel" alt="Vercel">
<img src="https://img.shields.io/badge/MCP-AI%20Agent%20API-FF6F00?style=for-the-badge" alt="MCP">
<img src="https://img.shields.io/badge/Sentry-crash%20reporting-362D59?style=for-the-badge&logo=sentry" alt="Sentry">
</p>

Copy `.env.example` to `.env.local` and uncomment the Supabase variables to enable Google sign-in and cloud backup.
<br />

## Deployment
---

Deploys automatically from `main` to Vercel:
## Version Journey

```bash
npx vercel --prod
```
| Version | Date | Highlights |
|---------|------|------------|
| **v0.11.0** | 2026-06 | Receipt capture, cloud sync, MCP server |
| **v0.10.0** | 2026-05 | Goals, recurring entries, CSV import engine |
| **v0.9.0** | 2026-05 | Budgets, search with Quick Jump |
| **v0.8.0** | 2026-04 | Guest mode, PWA readiness |
| **v0.7.0** | 2026-04 | Transaction search, filters, sortable columns |
| **v0.6.0** | 2026-03 | Multi-account support, CSV import |
| **v0.5.0** | 2026-03 | Accounts, transaction CRUD |
| **v0.4.0** | 2026-02 | IndexedDB persistence, local-first architecture |
| **v0.3.0** | 2026-02 | TypeScript migration, Tailwind CSS |
| **v0.2.0** | 2026-01 | Basic ledger UI, manual entry |
| **v0.1.0** | 2026-01 | Initial prototype |

Required environment variables for production:
- `NEXT_PUBLIC_SUPABASE_URL` — Supabase project URL
- `NEXT_PUBLIC_SUPABASE_ANON_KEY` — Public anon key
- `SUPABASE_SERVICE_ROLE_KEY` — For MCP token auth (server-only)
[Full Changelog](CHANGELOG.md)

## What's Next
<br />

See [ROADMAP.md](ROADMAP.md) for planned work. Current release is **v0.9.11** — Release Readiness.
---

## License

AGPL-3.0-or-later. See [LICENSE](LICENSE).
AGPL-3.0-or-later — see [LICENSE](LICENSE)

Built by [@sparshsam](https://github.com/sparshsam)

<br />

---

## Part of the Open Collection

<p align="center">
<table>
<tr>
<td align="center" width="200">
<img src="https://raw.githubusercontent.com/sparshsam/openpalette/main/assets/branding/icon.png" width="48" alt="OpenPalette"><br />
<strong>OpenPalette</strong><br />
<sub>A color studio for designers</sub><br />
<a href="https://github.com/sparshsam/openpalette">Repo</a> ·
<a href="https://palette.kovina.org">Web</a>
</td>
<td align="center" width="200">
<img src="https://raw.githubusercontent.com/sparshsam/opensend/main/assets/branding/opensend-icon.png" width="48" alt="OpenSend"><br />
<strong>OpenSend</strong><br />
<sub>Free file sharing, no account needed</sub><br />
<a href="https://github.com/sparshsam/opensend">Repo</a> ·
<a href="https://send.kovina.org">Web</a>
</td>
<td align="center" width="200">
<img src="https://raw.githubusercontent.com/sparshsam/opensprout/main/assets/branding/icon.png" width="48" alt="OpenSprout"><br />
<strong>OpenSprout</strong><br />
<sub>Plant care records</sub><br />
<a href="https://github.com/sparshsam/opensprout">Repo</a> ·
<a href="https://sprout.kovina.org">Web</a>
</td>
<td align="center" width="200">
<img src="https://raw.githubusercontent.com/sparshsam/OpenTone/main/assets/branding/icon.png" width="48" alt="OpenTone"><br />
<strong>OpenTone</strong><br />
<sub>Offline music library</sub><br />
<a href="https://github.com/sparshsam/OpenTone">Repo</a>
</td>
</tr>
</table>
</p>

<p align="center">
<a href="https://github.com/sparshsam?tab=repositories&q=open&type=public">View all Open* repositories →</a>
</p>
Binary file added assets/branding/icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/branding/icon-source.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions assets/branding/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/gallery/dashboard-mobile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/gallery/screenshot-main.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/gallery/screenshot-search.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/hero/dashboard-desktop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions docs/Architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Architecture

> Full architecture documentation at [`docs/architecture.md`](architecture.md) (existing).

## Overview

OpenLedger is a **local-first** single-page application. The entire ledger runs in the browser with IndexedDB as the primary data store and localStorage as a fallback. Cloud sync via Supabase is optional and opt-in.

## Stack

```
Framework: Next.js 16 (App Router)
Language: TypeScript 5
Styling: Tailwind CSS 4 + custom CSS
State: React hooks + IndexedDB persistence
Auth: Supabase Auth (Google OAuth) — optional
Cloud: Supabase Postgres (Elora project, openledger_ prefix)
Crash: Sentry (optional)
Hosting: Vercel → ledger.kovina.org
License: AGPL-3.0-or-later
```

## Storage Architecture

```
Browser (Next.js SPA)
├── IndexedDB — primary data store
├── localStorage — secondary store (learnings, rules, settings)
├── Service Worker — offline cache, PWA shell
├── Supabase Auth — optional Google sign-in
├── Supabase Postgres — optional cloud backup
└── Supabase Storage — optional receipt photos
```

## Additional Resources

- [Architecture (full)](architecture.md)
12 changes: 12 additions & 0 deletions docs/Contributing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Contributing

> The full contributing guide is at [`CONTRIBUTING.md`](../CONTRIBUTING.md).

## Quick Summary

1. Create a feature branch from `main`
2. Run all checks before submitting
3. Keep changes focused — one feature per PR
4. Update CHANGELOG.md

By contributing, you agree that your contributions will be licensed under AGPLv3.
Loading
Loading