SlowBooks Pro
Free accounting software for Windows, Mac, and Linux. Payroll, inventory, unlimited invoicing, multi-user Server Edition built into the signed installer (no Docker required). No cloud, no subscription
Your money as a pie: see what is left in proportions, not numbers.
FinanceTypeScript · PLpgSQLGitHub @rosneriOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Your money as a pie. Instead of numbers and budgets, pienance talks in rough proportions: "Fits. It is about a fifth of your Wants slice and leaves about two thirds of it."
It answers two questions:
| Term | Meaning |
|---|---|
| Pie | The monthly income. The aggregate root. |
| Slice | A named share of the pie (Needs 50%, Wants 30%, Savings 20%). |
| Bite | An expense, taken from one slice. |
| Bake | Create the pie from a monthly income. |
| Weigh | Consider a bite without taking it: how big is it, what would be left? |
| Put back | Remove one of this month's bites, as if it was never taken. |
| Move | Take one of this month's bites out of its slice and into another. |
| Reset | Start over: the pie goes, with every month of bites and staples. |
| Re-slice | Change the pie's income or its slices (names, shares, adding, retiring). |
| Retired | A removed slice: it keeps its past bites but no longer takes a share. |
| Spread | One expense split into equal bites over several months, starting now. |
| Carry | Last month's leftover, added to one slice of this month's pie. |
| Sweep | The difference between a bite and its rounded-up amount, put into one slice. |
| Verdict | fits, tight (leaves only crumbs) or overflows (more than left). |
| Serving | A slice with how much of it is eaten and left this month. |
| Leftover | What is left of the whole pie this month. |
| Staple | A bite that comes back every month, e.g. rent from Needs. |
| Pantry | All of a pie's staples. |
| Pace | How fast a slice is eaten compared with how much of the month is gone. |
| Shelf | The past months of a pie, each shown as its own small pie. |
| Appetite | How much of a slice is usually eaten by the end of a month. |
| Overview | The whole pie at once: every slice, staple and bite. |
| Focus | A single view of the pie through one cut, told in a sentence. |
| Cut | How a focus slices the pie: a slice, every month or one time. |
| Proportion | A ratio. A part of a slice is a simple fraction, "1/30 (Wants)"; the rest is said roughly ("about a quarter left"). |
| Statement | A bank's CSV or Excel export, in any layout; its spends become draft bites. |
These words are used as-is in code, UI, agent tools and conversation.
Managed with moon (tasks, project graph, boundaries, CI) and
proto (tool versions, pinned in .prototools), on pnpm workspaces.
packages/core @pienance/core Pure TypeScript: domain, use cases, views. No Node, DOM or framework.
packages/db @pienance/db Prisma Postgres adapter for the PieRepository port. Server only.
packages/ui @pienance/ui Shared shadcn/ui components + design system (Tailwind v4).
packages/auth @pienance/auth Better Auth: email + password, JWT sessions, JWKS. Server only.
packages/telemetry @pienance/telemetry OpenTelemetry traces, vitals, events → Postgres.
apps/web @pienance/web Next.js app (Vercel): UI, server actions, WebMCP tools.
tools/oxlint anti-slop Vendored Oxlint rules (github.com/dmmulroy/anti-slop).
.claude/skills hallmark, install-anti-slop Vendored agent skills for design and lint upkeep.
@pienance/core holds everything a future native app needs: the domain (Pie, Slice, Bite,
Money, Currency, Proportion, roughly()), the use cases wired through Ports (repository, ids, clock),
serialisable views, the sentences users read, and the SVG geometry of the pie. Its tsconfig.json
has no DOM or Node types, so anything platform-specific fails to compile.
Boundaries are enforced three ways:
application → library) and tags (portable only depends on portable).no-restricted-imports per package (core imports no framework, Node or sibling).Pienance is an app, not a content site: it reads and writes data on every interaction. Next.js server actions keep that simple, and React carries over to React Native when the native app comes. Astro shines for content-first sites, which this isn't.
Better Auth (packages/auth), with email and password accounts.
Sessions are cached in a signed JWT cookie, and the JWT plugin issues JWTs at
GET /api/auth/token and publishes their public keys at GET /api/auth/jwks, so APIs and a
future native app (Better Auth has an Expo client) can verify users without calling back. Users,
sessions and keys live in Postgres next to the pies; every pie belongs to a user, and the core's
use cases take that ownerId explicitly.
Every user has a role, stored in Postgres (user.role, a Role enum): member by default, or
admin. Permissions are CASL abilities defined in one place,
abilityFor(viewer) in packages/auth/src/access.ts; pages check them with
abilityFor(await viewerOf(auth(), headers)).can("read", "Telemetry"). Today admins may read
telemetry (/admin). Pies need no rule: the use cases already scope them to their owner.
Roles are granted in the database only. Sign-up and profile updates can never set them:
UPDATE "user" SET "role" = 'admin' WHERE "email" = '[email protected]';
The role rides in the session cookie cache, so a change applies within 5 minutes, or at once after signing in again.
Every pie has an ISO 4217 currency, chosen when it is baked; its bites are in the same currency.
Money in the core is a thin domain wrapper around Dinero.js v2, which
does the real work: currency definitions with the right minor units (JPY has none, KWD has
three), exact integer arithmetic, rounding, and allocate to cut the income into slices without
losing a cent. Amounts are stored in minor units with their currency code. Converting between
currencies (Dinero's convert plus a rates port) is the natural next step when a bite is paid in
another currency.
Components are shadcn/ui, shared from packages/ui. The UI follows Hallmark (vendored in .claude/skills/hallmark):
a custom "cakes and pies, clean, minimalist" theme — cream paper, crust-tone slices, one berry
accent, Fraunces + Geist — on a mobile-first Map / Diagram layout where the pie is the page. The
system is stamped in packages/ui/src/styles/globals.css, using shadcn's token names
(--background, --primary, --ring…) so shadcn components pick it up unchanged.
The web app registers WebMCP tools so in-browser
agents can use pienance directly: bake_pie before a pie exists, then read_pie, weigh_bite
(read-only) and take_bite, plus read_statement (read-only) and take_bites to import a bank
statement, and reset_pie to start over. They call the same server actions as the UI, so the page stays in sync.
/import takes a CSV or spreadsheet (.xlsx, .xls, .ods) export from any bank. A
spreadsheet's first sheet is turned into CSV in the browser by SheetJS
(loaded only for spreadsheets; installed from its own CDN, as npm only has an old release), with
dates as 2026-10-03 (apps/web/src/import/spreadsheet.ts). Papa Parse splits the
file (any delimiter, quoting, line endings); then @pienance/core guesses the layout by rules
(guessLayout): preamble rows, which column is the day, amount, money out/in or description,
day order and decimal mark. Only when the rules are unsure, or to suggest a slice for each bite,
does the Advisor port ask a decision model through the AI SDK's experimental_decide and the
Vercel AI Gateway: Jev (typesafe-ai/jev) for now, to be
replaced with Cloudflare's Clef once the gateway serves it (apps/web/src/import/decision-advisor.ts).
A note the person already took from a slice in the last three months goes to that slice
again, so imports follow their own slicing; only the other notes, and the first rows, are sent. Without gateway access (no
AI_GATEWAY_API_KEY locally), the rules work alone. Re-importing a statement skips the bites
already taken. A statement over the limits (2,000 lines or 2M characters) is cut
on the server to its first lines that fit, and the page says how many it read. Files over 3.5 MB
are refused before upload.
proto use # installs node, pnpm and moon from .prototools
pnpm install
moon run web:dev # runs in memory when DATABASE_URL is not set
With a database:
cp packages/db/.env.example packages/db/.env # DATABASE_URL, for migrations
cp apps/web/.env.example apps/web/.env.local # DATABASE_URL, BETTER_AUTH_SECRET
moon run db:migrate
moon run web:dev
Vitest everywhere, moon run :test (or moon ci) runs them all. No module mocking (anti-slop
forbids it): dependencies are passed in, so tests hand in real in-memory adapters or plain
functions instead.
| Project | Unit | Integration |
|---|---|---|
| core | Money, Currency, Proportion, Month, roughly, Pie, views, sentences, geometry | use cases with the in-memory repository |
| db | — | PrismaPieRepository against a real Postgres |
| auth | — | sign up/in/out, JWT cookie, /token JWTs verified with the JWKS (jose), on Postgres |
| ui | shadcn components (variants, states, form posting) | — |
| telemetry | beacon contract, batching queue, tail sampler, span and event mapping | Postgres writer, rollups and partitions |
| web | components and forms (Testing Library + jsdom), WebMCP tools, <Telemetry /> | server actions with auth + Postgres users, telemetry routes |
Integration tests get a throwaway Postgres from @pienance/db/testing: PGlite runs in-process,
served over the Postgres wire protocol, with the real migrations applied. No Docker needed.
Every project inherits lint (oxlint + anti-slop), format (oxfmt) and typecheck from
.moon/tasks/all.yml; projects tagged tested also get test (Vitest).
| Command | Does |
|---|---|
moon check --all | every task of every project |
moon ci | only what a change affects (used in CI) |
moon run :lint | lint everything |
moon run core:test | test the core |
moon run web:build | production build |
moon run db:migrate | create/apply a migration in development |
moon project-graph | see how the projects depend on each other |
moon installs a pre-commit hook that lints and format-checks staged changes.
.github/workflows/standards.yml checks every PR:
moon ci: lint with anti-slop, format, typecheck, tests and build of affected projects.ANTHROPIC_API_KEY repository secret; skipped
on drafts.Traces, web vitals, product analytics and clickstream go into the same Postgres, in a separate
telemetry schema partitioned by day, with no collector or daemon
(docs/telemetry.md):
instrumentation.ts (Next.js, Prisma and each use case), tail
sampled per request and written after the response.pie.baked, bite.weighed, bite.taken, staple.stocked,
staple.dropped, statement.read, bites.taken, from the server actions.<Telemetry /> batches pageviews, data-track clicks and
vitals into beacons to POST /api/telemetry.Telemetry never records amounts or incomes.
Admin: /admin shows it over the last day, week or two weeks: totals, requests by route
(median and p95), failed and slowest requests with their trace waterfall, web vitals judged at
p75, the product funnel, pages and clicks. Only admins get in (see Roles); everyone else gets
a 404.
The repository deploys as is: vercel.json declares the web app as a Vercel service rooted at
apps/web, so no Root Directory setting is needed. Each build runs apps/web/scripts/vercel-build.mjs,
which applies pending Prisma migrations and then builds Next.js.
Environment:
postgres:// URL among DATABASE_URL, POSTGRES_URL, POSTGRES_PRISMA_URL.BETTER_AUTH_SECRET (openssl rand -base64 32) to sign sessions and JWTs.
Without it, a secret is derived from the database URL (server-only; whoever holds it can read
every pie anyway). Rotating it signs everyone out.BETTER_AUTH_URL for a custom domain.CRON_SECRET so the daily maintenance cron can run. Optionally set
TELEMETRY_DATABASE_URL (a pooled URL for a telemetry_writer role) and
TELEMETRY_SAMPLE_RATIO (share of ordinary traces kept, default 1).AI_GATEWAY_API_KEY to try it.