Oracle3
Open-source trading engine and MCP server for prediction markets. Fee-aware no-arbitrage trading across related contracts, live on Kalshi, Polymarket and Solana or on paper.
Personal finance, made clear. Track what you have, understand where it goes.
Translation pending
FinanceTypeScript · PLpgSQLGitHub @JRRS1982OnlineOwner 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
A personal finance app for budgeting, tracking expenditure and life planning
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Personal finance, made clear. Live at.
Most people trying to get a grip on their money build a spreadsheet, then
quietly abandon it around month three. Balanced Money is that spreadsheet with
the boring parts already done: the structure, the formulas, and the charts. You
still bring the numbers — what you don't have to do is decide how to organise
them.
It never connects to your bank. There is no Open Banking link and no third party
with read access to your accounts: figures get in via a CSV you export yourself,
or by typing.Read the full README ↗Personal finance, made clear. Live at https://balanced.money.
Most people trying to get a grip on their money build a spreadsheet, then quietly abandon it around month three. Balanced Money is that spreadsheet with the boring parts already done: the structure, the formulas, and the charts. You still bring the numbers — what you don't have to do is decide how to organise them.
It never connects to your bank. There is no Open Banking link and no third party with read access to your accounts: figures get in via a CSV you export yourself, or by typing.
The repository is named halcyon; the product it ships is Balanced Money. Same thing — the repo name predates the brand.
| Transactions | Export a CSV from your bank and drop it in. Rows you've already imported are detected and skipped, so overlapping exports are safe, and every import is a batch you can undo in one click. Tag each row with a category. |
| Budget | What you meant to spend, month by month, split into Fixed, Variable and Discretionary. Once transactions are categorised the actual column fills itself in beside your plan. Two more kinds of row sit alongside: a repayment at a debt you owe, which counts as spending, and a transfer into an account you own, which does not — a pension contribution is money you still have. Both feed the long-range plan. |
| Balance | What you own and what you owe, sorted by how soon it matters — current, medium-term, long-term, property. The bottom line is your net worth. |
| Dashboard | Read-only, and derived: cash flow, savings rate, spending by category and net worth over time, all drawn from the months filled in elsewhere. |
| Plan | The long view. Project income, spending, property, mortgages and pensions decades ahead to see whether the money lasts. Independent of the month-to-month figures. |
| Settings | Currency and number format, light/dark/system, which charts appear, categories and accounts — plus a full JSON export of your data and a permanent delete. |
There is a guide at /about explaining the
monthly rhythm the app is built around, reachable without an account.
Built as a learning project, and documented like one. Start with the Playbook for how it was approached, or the docs directory for architecture and design.
pnpm dev or make up).[email protected] contact address named in the legal pages) is ImprovMX forwarding — MX + SPF records live in Vercel DNS, the forwarding destination in the ImprovMX dashboard. See docs/engineering/contact-email.md.master trigger GitHub Actions (.github/workflows/ci.yml) which runs biome ci, tsc --noEmit, Jest, and Playwright on Node 22 + pnpm 11. Vercel watches master independently and ships the build to production once its own build passes.migrate-prod job in .github/workflows/ci.yml runs against the production (unpooled Supabase connection, port 5432, supplied via the repo secret) — but only on push to and only after lint/test + e2e pass. Vercel is configured to wait for this workflow before deploying, so the new code never goes live against an un-migrated schema. Migrations are forward-only; to undo, write a corrective migration. Manual fallback: with set.Install dependencies with pnpm, then run the app in Docker for local development (this is what points it at the local database — see below):
pnpm install # install dependencies
make build # first run: build images, start Docker, migrate + seed (http://localhost:3210)
# thereafter: make # start the app and local Postgres (attached)
make vs pnpmmake for the app + the database (runs inside Docker, against local Postgres): make / make build (first-run setup) / make up / make down / make rebuild, make migrate-create name=<verb_table> (author a new migration), make migrate-deploy (apply pending migrations), make db-reset, make db-seed, make db-shell.pnpm for stateless checks (faster, and what CI runs): pnpm typecheck, pnpm check (lint+format), pnpm test, pnpm build, pnpm verify.make migrate-create / make migrate-deploy, never host pnpm prisma … — see the gotcha below.Two databases exist: local Postgres (the Docker db service) and production Supabase. Production DB URLs live only in Vercel env vars and CI secrets — no local file holds them. Locally it shakes out as:
| Command | Reads | Hits |
|---|---|---|
App in Docker — make up | compose.yaml env (local) | local |
App on host — pnpm dev (Next.js) | .env.development → .env | local |
Prisma CLI on host — pnpm prisma … | nothing (prisma.config.ts loads no env file) | fails loudly |
Two local env files, two roles: .env.development (committed) holds non-secret defaults — the local DB URL; the gitignored .env holds only the Supabase auth values (URL + keys, no DB URLs) — it's also the only file Docker Compose can interpolate ${...} from, which is why the secrets live there and not in a .env.local.
Prisma migrations always run inside the container — make migrate-create / make migrate-deploy — where compose.yaml pins DATABASE_URL/DIRECT_URL to the local db service. A stray host pnpm prisma migrate fails loudly (no connection string) instead of silently touching anything.
I have done my best, with the support of AI to put a comprehensive set of documents in place to help me and others understand the project and its architecture.
The unit tests run against the code in the src/ directory, rather than the container code, which improved the speed and reliability of the tests. In other projects i have worked on, running tests against the container code was a common source of frustration.
Tests sit beside the file they test: period.test.ts next to period.ts,
actions.createPlan.integration.test.ts next to actions.ts. Only the e2e
suite and the integration harness live in tests/. A unit test
(src/lib/ci/testSiblings.test.ts) fails if any test's subject file is missing.
To run the unit tests, use the following command: pnpm test, or one of the helpers listed below:
make testmake test-watchmake test-coverageServer actions and DB queries (imports, categorisation, merge, provisioning,
ledger queries) are tested against a real halcyon_test database, with only
the Supabase auth boundary mocked. Files use the *.integration.test.ts suffix and run
in a node-env Jest project, separate from the unit run.
pnpm test:integration
It needs a Postgres reachable at localhost:5432 (the db container from
make up is fine — the test database halcyon_test lives alongside the dev
halcyon DB). The command pins DATABASE_URL at halcyon_test and a guard
refuses to run against anything else; globalSetup applies migrations.
Run the tests locally:
Install browser system deps once: sudo npx playwright install-deps.
Install the project deps: pnpm install.
Install the browsers if missing: pnpm exec playwright install chromium.
Run the tests:
make test-e2e # all specs
make test-e2e name="transfers journey" # only specs/tests matching the grep
make test-e2e brings the local Postgres up and migrates halcyon_test
first (see below), then runs Playwright. To run Playwright directly instead:
pnpm exec playwright test (or --grep "<pattern>", or pnpm test:e2e:ui
for the UI runner). Avoid pnpm test:e2e -- --grep: the bare -- reaches
Playwright, which reads --grep as a positional file filter ("No tests
found").
Playwright spins up two webservers automatically:
localhost:54321 (see tests/e2e/_mock/supabase.mjs)localhost:3100 (the deliberately-different port lets the test server coexist with a developer's own pnpm dev on :3210)Auth is always mocked (no real Supabase project is touched). DB-touching
journeys (transactions, transfers) do hit a real halcyon_test Postgres at
localhost:5432, connecting as test:test to match the CI Postgres service.
The db container provisions halcyon_test and the test role automatically
on first volume init (see docker/postgres-init.sql),
and make test-e2e applies migrations to it — so a cold make test-e2e works
end to end. Coverage and approach are documented in docs/features/auth.md.
To seed the local development database, use the following command: pnpm db:seed, or one of the helpers listed below to seed and reset the database in the container.
make db-seedmake db-resetLanding-page screenshots live in public/marketing/ (dashboard.png, budget.png, balance.png, transactions.png, plan.png).
Re-capture them whenever the dashboard, budget, balance, transactions or plan UI changes — they are the first thing a prospect sees, and a stale set advertises a product that no longer exists.
The capture runs entirely locally against the e2e stack: the mock auth server, the halcyon_test database, and a dev server. Nothing touches cloud Supabase or production data, and the script signs itself in and seeds its own twelve months of demo data, so there is no session to set up by hand. It then creates the plan through the real form — creating a plan is a Sync against an empty one, so its rows come from the seeded accounts by the same path a user takes — and sets the assumptions a Sync can't know (mortgage rate and repayment, expected returns) before shooting.
It expects the signed-in demo user to be the only user in halcyon_test; leftovers from an earlier e2e run make it seed one user and photograph another. TRUNCATE "User" CASCADE clears them.
make e2e-db # local Postgres, migrated
node tests/e2e/_mock/supabase.mjs & # mock auth on :54321
NEXT_PUBLIC_SUPABASE_URL=http://localhost:54321 \
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_test_anon_key_for_e2e \
SUPABASE_SECRET_KEY=sb_secret_test_key_for_e2e \
DATABASE_URL=postgresql://test:test@localhost:5432/halcyon_test \
DIRECT_URL=postgresql://test:test@localhost:5432/halcyon_test \
pnpm next dev -p 3100 &
node scripts/capture-shots.mjs
The script refuses to run against anything but a local halcyon* database. Set CAPTURE_SCHEMES=light,dark to also produce -dark.png variants for design review — the landing page ships the light set only, since it is seen signed-out and serving both would mean downloading both.
Until the files exist the landing page renders labelled placeholders via MarketingShot, so the page ships and works correctly without them.
Contributions are always welcome! Please open a pull request or issue to discuss any changes you would like to make.
Issues and pull requests are welcome on GitHub.
prisma migrate deployDIRECT_URLPROD_DIRECT_URLmasterpnpm exec prisma migrate deployDIRECT_URL.env.example lists every variable and where it is set in each environment (Vercel, GitHub secrets, Supabase dashboard, local files). See also ADR-004.