Skip to content

radicand/simple-books

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

94 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

simple-books

Calm, real double-entry bookkeeping for sole proprietors who sell services.

simple-books is a bookkeeping platform built for one person: the owner of a service business who does not need (or want) QuickBooks. It produces a real set of books — every entry posts to a balanced double-entry journal — without ever asking the user to read one.

Balance sheet

What it does today

  • Service products — what you sell, with a rate per unit (hour, session, project…).
  • Customers — just enough info to attach to invoices.
  • Invoices — line items, automatic numbering (YYYY-NNNN), status (open · paid · void). Records only — no email, no payment processing, no PDFs - this is for you, it is not a customer portal. Edit open invoices with no payments (reverses and reposts the journal entry).
  • Cash receipts — log payments as they come in. If there isn't an invoice yet, one is created automatically and the same transaction posts it. Method-aware (cash, check, card, transfer, other). Stand-alone payments keep the auto-created invoice in sync.
  • Mileage — record business driving with the IRS standard rates (default $0.725/mile in 2026); each trip credits Owner's Contribution and debits Vehicle Expense. Trips can be edited after the fact if needed.
  • Reports — Balance Sheet and Cash Flow, rendered as readable tables. No fancy charts, by design. Assets always equal Liabilities + Equity.

Behind the scenes every event becomes a balanced journal entry — see DESIGN.md §5–7 for the data model and posting rules and .agents/skills/accounting-posting/SKILL.md for the engineering recipe.

Stack

Layer Choice
Runtime Bun
Build Vite
Server Nitro (Bun preset, via nitro/vite)
App TanStack Start (React + TanStack Router + TanStack Query)
Styling Tailwind with a custom OKLCH theme and Google's DESIGN.md pattern
DB SQLite (local dev) or PostgreSQL (production) via Drizzle ORM
Auth Better Auth — email/password + generic OIDC plugin
E2E Playwright (bun run build:e2e && bun run test)

No Next.js. No Node. No React server components. ESM only.

Quickstart

# 1. Install Bun if you don't have it
curl -fsSL https://bun.sh/install | bash

# 2. Install + initialize
bun install
cp .env.example .env
bun run auth:secret   # copy the printed value into BETTER_AUTH_SECRET
bun run db:migrate
bun run db:seed

# Optional: PostgreSQL (recommended for any real deployment)
# docker run -d --name simple-books-pg -e POSTGRES_USER=simplebooks \
#   -e POSTGRES_PASSWORD=secret -e POSTGRES_DB=simplebooks -p 5432:5432 postgres:18
# export DATABASE_URL=postgresql://simplebooks:secret@localhost:5432/simplebooks
# bun run db:migrate && bun run db:seed

# 3. Dev server (http://localhost:3000)
bun run dev

The very first visit to /login will offer to create your owner account — there is only one owner per install. Subsequent visits show normal sign-in and (if configured) the OIDC button.

Optional: OIDC provider

Fill in the four OIDC_* env vars in .env. The discovery URL is built from OIDC_ISSUER_URL. Register the redirect URI as <BETTER_AUTH_URL>/api/auth/oauth2/callback/oidc in your IdP.

SSO behavior (operators): When OIDC is configured, successful sign-in from your IdP will auto-provision a new app user if that email is not already in the database, or link the OIDC identity to an existing user when the email matches (for example the owner who first signed up with email/password). Access control is entirely through your identity provider — do not wire up arbitrary “social login” OAuth apps (Google, GitHub, etc.) unless you intend everyone who can use that client to reach the books. After the first user exists, additional people should be added in your IdP, not via public email sign-up. The system is really intended to be used with OIDC, even if lightweight. Auth0 is one of many good free options for small teams.

Database

  • SQLite (DATABASE_URL=./data/simple-books.db) — zero setup, good for local dev and quick demos. Not recommended for production: the database file lives on disk (or a PVC) and can be lost if the volume is deleted, the node fails, or the file is corrupted, or is manually edit and corrupts the SQLite WAL.
  • PostgreSQL (DATABASE_URL=postgresql://…) — use for any real-world install. Helm can bundle a Bitnami Postgres subchart (postgresql.enabled) or point at managed Postgres (database.externalUrl). Argo CD / GitOps: use an external Secret for Postgres credentials (postgresql.auth.existingSecret or database.existingSecretName); see deploy/helm/simple-books/README.md. Migrations live in drizzle/pg/; SQLite migrations stay in drizzle/.
bun run db:generate       # SQLite schema changes
bun run db:generate:pg    # PostgreSQL schema changes
bun run db:migrate        # applies the right folder for DATABASE_URL

Production build

bun run build      # -> .output/server/
bun run start      # -> bun run .output/server/index.mjs

Smoke test

bun run build:e2e   # production build with frozen REFERENCE_DATE
bun run test        # prod server + ephemeral SQLite DB

The test walks the entire sole-proprietor flow. To refresh committed README images in docs/screens/, run bun run screenshots. Normal bun run test does not touch those files.

Documentation

  • PROMPT.md — original task, frozen.
  • DESIGN.md — architecture, data model, posting rules, security posture, visual design system. The source of truth for design consistency.
  • .agents/skills/Agent Skills (skill-name/SKILL.md) for stack, posting, UI, deployment, and testing.

A tour

Page Screenshot
Dashboard
Invoices
Mileage
Balance Sheet
Cash Flow

License

MIT. See LICENSE.

About

Dead simple bookkeeping for busy, nontech, nonfinance people who just need to track their stuff.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors