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
33 changes: 7 additions & 26 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,10 @@ Thanks for contributing to Freenary.
## Before You Start

- Read [`CONTEXT.md`](../CONTEXT.md) — Freenary is an open-source personal finance and wealth-management platform. Keep changes aligned with that vision.
- Read [Contribute](../apps/fumadocs/content/docs/next/contribute.mdx) in the documentation for the full workflow, and [`docs/engineering`](../docs/engineering) for how the internals work.
- Set up from [Contribute](../apps/fumadocs/content/docs/next/contribute.mdx) in the documentation: it holds the first-run steps and both ways to run the code. This file holds the rules a pull request follows. [`docs/engineering`](../docs/engineering) covers how the internals work.
- Keep changes scoped to a clear user-facing improvement, bug fix, or refactor.
- Follow the code standards in [`AGENTS.md`](../AGENTS.md) — the repo uses Ultracite (Oxlint + Oxfmt) with strict, auto-fixable rules.

## Local Setup

Containerised stack (needs Docker and a free port 80, applies the migrations for you):

```bash
bun install
bun run dev:up # PostgreSQL, migrations, API server, web app, docs site
```

Local stack, with the applications on your host:

```bash
bun install
cp .env.example .env # the Postgres container reads the root .env
bun run db:start # starts the Postgres container
bun run db:push # applies the Prisma schema
bun run dev # web on 3001, server on 3000, docs on 4000
```

There is no seed script. Create an account through the sign-in screen. `bun run dev:up` configures no email provider, so sign-up returns a session at once and asks for no code — and so does the `bun run dev` path above. To work on the one-time-code flows, start the stack with `bun run dev:mail` instead: it adds a Mailpit inbox and points the API server at it, so the sign-up code, the verification code and the password reset all land in that inbox. See [Contribute](../apps/fumadocs/content/docs/next/contribute.mdx) for the details, and [Configuration](../apps/fumadocs/content/docs/next/reference/configuration.mdx) for every environment variable.

## Branch Naming

Use a clear, descriptive branch name that reflects the change.
Expand All @@ -44,19 +23,21 @@ Avoid vague names like `test`, `misc`, or `changes`.

## Before Opening a PR

Run the same checks that CI runs, in this order:
Run the same commands as CI's `ci` job, in this order:

```bash
bun install --frozen-lockfile
bun run check # Oxlint + Oxfmt
bun run check-types # TypeScript
bun run check:fsd # Feature-Sliced Design layers and public APIs
bun run docs:check # documentation gate
bun run env:check # .env.example and the configuration reference match packages/env
bun run build # every app
```

Most lint/format issues are auto-fixable with `bun run fix`.

CI runs one more job that no root script covers: it parses every Compose file with `docker compose config --quiet`, and it asserts that `docker-compose.yml` still refuses an empty `POSTGRES_PASSWORD` and `BETTER_AUTH_SECRET`. Reproduce it before you change either file.
CI's `compose` job has no root script. It parses `docker-compose.dev.yml` (alone and with `docker-compose.mail.yml`), `docker-compose.proxy.yml`, `docker-compose.yml`, `deploy/docker-compose.yml` and `deploy/coolify.yml` with `docker compose config --quiet`. It also asserts that `docker-compose.yml` refuses an empty `POSTGRES_PASSWORD` and `BETTER_AUTH_SECRET`, and that `deploy/docker-compose.yml` refuses an empty `FREENARY_URL`, `POSTGRES_PASSWORD` and `BETTER_AUTH_SECRET`. Reproduce it from [`.github/workflows/ci.yml`](workflows/ci.yml) before you change any of these files.

CI runs no tests, and there is no root `test` script. Run the test files your change touches by hand with `bun test <path>`.

Expand All @@ -70,7 +51,7 @@ If your change alters documented behavior — a screen, an API route, an environ

Follow the [pull request template](pull_request_template.md). Each pull request should:

- open against `dev` — `main` holds released code, and `dev` is the branch a release is cut from
- open against `dev`; `main` holds released code, and a release is cut from `main` after `dev` merges into it
- explain the user-visible change
- stay focused on a single topic when possible
- include screenshots or screen recordings for new UI or behavior changes
Expand All @@ -94,4 +75,4 @@ Do not paste code from a source whose license forbids it, and do not add a depen

## Release Process

Releases are maintainer-managed: a maintainer merges `dev` into `main` and runs the `Release` workflow, which creates the tag, the images and the GitHub release. Do not tag, and do not include a version bump in a normal contribution unless a maintainer asks for one. See [Contribute](../apps/fumadocs/content/docs/next/contribute.mdx).
Releases are maintainer-managed: a maintainer merges a docs snapshot (`cd apps/fumadocs && bun run docs:snapshot X.Y.Z`) into `dev`, merges `dev` into `main`, and runs the `Release` workflow, which creates the tag, the images and the GitHub release. Do not tag, and do not include a version bump in a normal contribution unless a maintainer asks for one. See [`docs/engineering/releasing.md`](../docs/engineering/releasing.md).
6 changes: 4 additions & 2 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[summary]: #summary

Describe the change in one paragraph.
At most four sentences: what changed, and what a reviewer should look at first.

# Motivation

Expand All @@ -24,4 +24,6 @@ How have similar problems been solved elsewhere — what worked, what didn't?

# Notes

Flag anything reviewers should know: migration steps, risks, or follow-up work.
[notes]: #notes

One line per fact: `Closes #n`; the visual change, or "no visual change"; the tests added; the `apps/fumadocs` pages updated, or "none" and why; any migration, breaking change or merge-order constraint.
14 changes: 9 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ bun run dev:up # PostgreSQL, migrations, API server, web app, docs site
`dev:up` runs `docker-compose.dev.yml` under a per-worktree Compose project and prints the URLs it serves. No dev service publishes a host port: one shared Traefik on port 80 routes plain-HTTP hostnames (`web.<slug>.freenary.localhost`, `server.<slug>.freenary.localhost`, `docs.<slug>.freenary.localhost`) to the containers, and the slug comes from the git branch. `scripts/dev.ts` reuses a Traefik already on the `devproxy` network, or starts `docker-compose.proxy.yml`; the self-hosting `docker-compose.yml` never involves it. Use Chrome or Firefox, which treat `*.localhost` as a secure context. Without Docker for the apps, use the local path instead:

```bash
bun run db:start # PostgreSQL container from docker-compose.yml (needs the root .env: cp .env.example .env)
bun run db:push # apply the Prisma schema
bun run dev # web 3001, server 3000, docs 4000
cp .env.example .env # POSTGRES_PASSWORD and BETTER_AUTH_SECRET for docker-compose.yml
echo 'DATABASE_URL=postgresql://postgres:password@localhost:5432/freenary' > apps/server/.env
docker compose up -d --wait postgres
(cd packages/db && bun run db:migrate:deploy) # the Prisma CLI reads DATABASE_URL from apps/server/.env
bun run dev # web 3001, server 3000, docs 4000
```

The dev stack needs no `.env`: the `server` service declares `env_file` with `required: false`, so an optional root `.env` reaches the container line by line, and `environment` carries only the six values the stack derives from the worktree — `DATABASE_URL`, `BETTER_AUTH_SECRET`, `BETTER_AUTH_URL`, `CORS_ORIGIN`, `AUTH_COOKIE_DOMAIN` and `NODE_ENV` (Compose gives `environment` precedence over `env_file`). It configures no email provider, so the one-time-code flows are off. `bun run dev:mail` layers `docker-compose.mail.yml` over it: that file starts `axllent/mailpit:v1.28` and points the server at it with `EMAIL_PROVIDER=smtp`, `SMTP_HOST=freenary-mailpit`, `SMTP_PORT=1025` and `EMAIL_FROM=Freenary <no-reply@freenary.test>`, and the inbox is a web page at `http://mail.<slug>.freenary.localhost`. `bun run dev:reset` destroys the volumes and starts over. The `bootstrap` service runs `prisma migrate deploy` before the API server starts.
Expand Down Expand Up @@ -79,6 +81,8 @@ Pure refactors, internal helpers, and dependency bumps that change no documented

**Document what is true, and only what is true.** Read the code before writing the page, quote real names, and never describe a screen, flag, or endpoint that does not exist. Write plain, short, second-person prose; the full writing rules are in [`apps/fumadocs/AGENTS.md`](apps/fumadocs/AGENTS.md).

**A page is not evidence.** Existing documentation, including this file, can be stale or machine-written, so verify every technical claim against code, tests, schemas, command output or an approved specification before you repeat it. Never grow an existing page by paraphrasing it: update only the pages the change affects, keep accurate human-written text as it is, and delete what is obsolete or redundant. Never state a reason behind a design choice that the code does not show; ask a maintainer instead.

**Verify it.** Two gates, and neither one alone is enough:

```bash
Expand Down Expand Up @@ -114,14 +118,14 @@ The rules live next to the code they govern: [`apps/web/AGENTS.md`](apps/web/AGE

## Branches and Releases

Pull requests target `dev`, the integration branch; `main` holds released code, and a push to either branch publishes the `ghcr.io/suiramdev/freenary-server` and `ghcr.io/suiramdev/freenary-web` images under that branch name. A maintainer releases by merging a docs snapshot (`bun run docs:snapshot X.Y.Z`) into `dev`, merging `dev` into `main`, and running the `Release` workflow, which refuses a stable version without its snapshot, then creates the `vX.Y.Z` tag, the versioned images and the GitHub release. The web image carries its version from the build argument `FREENARY_VERSION`, which is what its account-menu documentation link points at. Contributors never tag and never bump a version — see [Contribute](apps/fumadocs/content/docs/next/contribute.mdx).
Pull requests target `dev`, the integration branch; `main` holds released code, and a push to either branch publishes the `ghcr.io/suiramdev/freenary-server` and `ghcr.io/suiramdev/freenary-web` images under that branch name. A maintainer releases by merging a docs snapshot (`cd apps/fumadocs && bun run docs:snapshot X.Y.Z`) into `dev`, merging `dev` into `main`, and running the `Release` workflow, which refuses a stable version without its snapshot, then creates the `vX.Y.Z` tag, the versioned images and the GitHub release. The web image carries its version from the build argument `FREENARY_VERSION`, which is what its account-menu documentation link points at. Contributors never tag and never bump a version — see [Contribute](apps/fumadocs/content/docs/next/contribute.mdx).

## Pull Request Descriptions: Complete, Then Brief

- **Reviewers skim.** A description they have to scroll does not get read, so keep the whole body under ~400 words. Fill every section; pad none.
- **Summary:** at most four sentences — what changed, and what to look at first.
- **Motivation, Drawbacks, Prior art:** at most four short bullets each. Drawbacks and Prior art carry the honest costs and the rejected alternatives, not a sales pitch.
- **Notes:** one line per fact — `Closes #n`, the visual change (or explicitly none), the tests added, the `apps/fumadocs` pages updated (or explicitly none, and why), the short review summary `CONTRIBUTING.md` asks for, and any migration, breaking change, or merge-order constraint.
- **Notes:** one line per fact — `Closes #n`, the visual change (or explicitly none), the tests added, the `apps/fumadocs` pages updated (or explicitly none, and why), and any migration, breaking change, or merge-order constraint.
- Don't restate the issue, list changed files, narrate the implementation, or paste command output — reviewers open the diff and the linked issue for that.
- Evidence a reviewer may want but need not read (verification logs, benchmark runs) belongs in a PR comment, not the description.
- A section that needs a table or a code block is a smell: that detail belongs in the issue, the code, or a comment.
Expand Down
2 changes: 2 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Areas are perspectives on one shared model — never independent mini-applicatio

Terms defined here are canonical; do not drift to synonyms.

The shipped app and the docs word some of them differently: a **Connection** is a "bank connection", an **Account** below is a "bank account" there, "account" alone means the sign-in account, a **Recurring expense** is a "recurring payment", and a **Budget period** is a "period".

- **Financial model** — the single internal representation of a user's financial life that every area reads from.
- **Connection** — the external institution/provider link through which data is synchronized (e.g. a bank connected via Powens).
- **Account** — a container of holdings within a connection or created manually (bank account, brokerage account, life-insurance contract, crypto account). Hierarchy: Connection → Account → Holding / Transaction.
Expand Down
19 changes: 2 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ The full documentation lives at [freenary.dev](https://freenary.dev) (source in
- [Use Freenary](https://freenary.dev/docs/use/budget): budget, bank connections, assistant, account
- [Run your instance](https://freenary.dev/docs/run/email): email, sign-in, updates, backups, troubleshooting
- [Reference](https://freenary.dev/docs/reference/configuration): configuration, bank providers, reverse proxy, API
- [Contribute](https://freenary.dev/docs/contribute): run the code, run the checks, open a pull request
- [Contribute](apps/fumadocs/content/docs/next/contribute.mdx): run the code, run the checks, open a pull request

## Development

Expand All @@ -29,22 +29,7 @@ bun install
bun run dev:up
```

`dev:up` runs everything in Docker at `http://web.<slug>.freenary.localhost`. Without Docker for the apps:

```bash
cp .env.example .env
bun run db:start
bun run db:push
bun run dev # web 3001, server 3000, docs 4000
```

Run the checks before opening a pull request:

```bash
bun run check # lint and format
bun run check-types # TypeScript
bun run build # every app
```
`dev:up` runs everything in Docker at `http://web.<slug>.freenary.localhost`. [Contribute](apps/fumadocs/content/docs/next/contribute.mdx) covers the local setup without Docker and the checks to run before a pull request.

## Contributing

Expand Down
Loading
Loading