PrimoDev/ apps

Recta

Personal and household finances in one place, on web, iOS and Android

  • Web
  • iOS
  • iPadOS
  • watchOS
  • Android
  • Self-hosted
  • Free
  • Open source · MIT

What is Recta?

Recta is a personal finance manager for organizing accounts, credit cards, statements, budgets and savings goals, on your own or with the people you live with. It runs on the web at recta.app and has native apps for iPhone, iPad, Apple Watch and Android.

Hosted Recta (web and apps) is free, with no paid plans, no ads and no credit card. There's also an MIT-licensed open source version (backend and web frontend) you can host on your own server, paying only for your hosting.

What it does

  1. 01Unlimited accounts and cards, with limits, closing and due dates, and monthly statements
  2. 02Installment purchases on cards, with each installment on the right statement
  3. 03Category budgets, savings goals and recurring transactions
  4. 04Shared household budget, with expenses split between members
  5. 05Reports by category and period, with data export
  6. 06iOS app with a widget, Siri and Shortcuts, Apple Watch and an iPad layout
  7. 07Available in 8 languages, with light and dark themes
  8. 08Open source self-hosted version with a Fastify and PostgreSQL backend

FAQ

Is Recta free?
Yes. According to the site there are no paid plans, no trial and no credit card, and every feature is available to everyone. The App Store and Google Play apps are free too.
Can I use Recta with my partner or family?
Yes. You invite the people you live with into the same household, set category limits together and split an expense between members. Read-only access is also available.
Is there an iPhone and Android app?
Yes. The iOS app runs on iPhone, iPad and Apple Watch (iOS 17 or later), and the Android app is on Google Play. The same account works on the web and in the apps.
Can I self-host Recta?
Yes. The backend (recta-selfhosted-backend) and web frontend (recta-selfhosted-frontend) are on GitHub. You need Node.js 20+ and PostgreSQL 16+, and the local auth mode lets you run it without Firebase.
What's the difference between recta.app and the self-hosted version?
recta.app is the hosted product, with the web app and native apps. The self-hosted version is the open backend and web code you run yourself. Contributions to the open repos don't guarantee a change ships on recta.app.
Does Recta show ads or track me?
No. The App Store description says the app has no ads and no tracking, and you can hide balances and lock the app with Face ID, Touch ID or your passcode.

Guides

Documentation

README from the lucianodiisouza/recta-selfhosted-backend repository, refreshed on every deploy.

Backend for Recta — personal finance app with household collaboration. Open source & self-hostable.

About this project

Recta is an open source personal finance manager. This repository is the public backend: anyone can self-host it, fork it, submit pull requests, or build on top of it. Submitting PRs or contributing does not guarantee that any feature or change will be incorporated into the hosted product at recta.app. The maintainers decide what is merged and what is shipped on recta.app.

This project is maintained by PrimoDev.

Other part of the project: recta-selfhosted-frontend — web app (React/Vite).

Tech stack

  • Node.js 20+
  • Fastify – REST API
  • PostgreSQL – database
  • Prisma – ORM
  • Firebase Admin – auth (Google, Apple, email)
  • Zod – validation

Hosting (self-hosted)

You can run this backend on any Node.js host. Some options:

  • Railway – simple deploy, PostgreSQL add-on, cron support
  • Render – free tier, PostgreSQL, background workers
  • Fly.io – global regions, PostgreSQL via Supabase or external
  • DigitalOcean App Platform – managed app + DB
  • VPS (Hetzner, Linode, etc.) – run npm run start behind Nginx and use a managed PostgreSQL (e.g. Supabase, Neon, or self-hosted)

Set DATABASE_URL, pick an auth mode and, in production, ALLOWED_ORIGINS and optionally SWAGGER_USERNAME/SWAGGER_PASSWORD. For recurring transactions, schedule npm run cron:process-recurrences once per day (cron job or Railway cron).

You don't need Firebase to run a working instance — local auth mode plus PostgreSQL is enough.

How to run

Prerequisites

  • Node.js 20+
  • PostgreSQL 16+
  • Firebase project with Authentication enabled

1. Install dependencies

npm install

2. Environment variables

cp env.example .env

Edit .env:

Variable Required Description
DATABASE_URL Yes PostgreSQL URL, e.g. postgresql://user:password@localhost:5432/recta
AUTH_MODE Yes local (no Firebase) or firebase (default). See below.

Auth mode

Choose how users sign in via AUTH_MODE:

  • local (recommended for self-host) — no third-party auth. The backend issues and verifies its own JWTs for email/password login. Requires AUTH_JWT_SECRET (min 32 chars; generate with openssl rand -base64 48). Optional: AUTH_TOKEN_TTL_HOURS (default 720 = 30 days), AUTH_REQUIRE_EMAIL_VERIFICATION (default false). No Firebase setup needed.
  • firebase (default) — Google/Apple/Email sign-in via Firebase. Provide credentials with one of the two options below. Optionally set the public AUTH_FIREBASE_WEB_API_KEY so GET /auth/config hands the client your web config.

Clients call GET /auth/config (public) to discover the mode before showing a login screen.

Firebase – option A (file):

  • Create a service account and download the JSON.
  • Save it in the project (e.g. firebase-service-account.json) and do not commit it.
  • In .env: GOOGLE_APPLICATION_CREDENTIALS=./firebase-service-account.json

Firebase – option B (env vars):

  • In .env set: FIREBASE_PROJECT_ID, FIREBASE_CLIENT_EMAIL, FIREBASE_PRIVATE_KEY (private key with \n for newlines).

Other optional vars: PORT (default 3000), REDIS_URL, SWAGGER_USERNAME/SWAGGER_PASSWORD, ALLOWED_ORIGINS, FIRST_RUN. See env.example.

In production use npm run db:deploy (not db:migrate) to apply migrations, or set FIRST_RUN=true on the first boot to run them automatically, then remove it.

3. Run migrations

npm run db:migrate

4. Start the server

Development:

npm run dev

Production:

npm run build
npm run start

API at http://localhost:3000. Swagger docs (when enabled): http://localhost:3000/docs.

5. Verify

curl http://localhost:3000/health

Returns { status, timestamp, uptime, apiVersion, minClientVersion }. apiVersion is the self-host contract: clients compare it against the official contract to detect a backend that has fallen behind. If your instance reports an older apiVersion than the app expects, pull the latest code and redeploy so the schema and endpoints stay in sync.

Scripts

Command Description
npm run dev Dev server with hot reload
npm run build Production build
npm run start Run production build
npm run db:migrate Run migrations (dev)
npm run db:deploy Run migrations (production)
npm run db:studio Open Prisma Studio
npm run db:generate Generate Prisma Client
npm run lint Lint
npm run typecheck Type check

Recurring transactions (cron)

To process recurring transactions daily, run as a cron job:

npm run build
npm run cron:process-recurrences

Schedule this once per day (cron, systemd, or your host’s scheduler).

Project structure

src/
├── app.ts              # Fastify app
├── index.ts            # Entry point
├── modules/            # API modules (auth, users, households, accounts, transactions, etc.)
├── shared/
│   ├── config/         # env, Firebase
│   ├── db/             # Prisma & migrations
│   ├── middleware/     # Auth & authorization
│   └── utils/
└── jobs/               # Cron (e.g. processRecurrences)

License

MIT