Skip to content

Repository files navigation

🍋 LimeBalance

A personal finance tracker you control straight from Telegram.
Log expenses and income in seconds, organize them into categories, and get instant multi-currency summaries — all backed by a clean, documented REST API.

NestJS TypeScript Fastify Prisma PostgreSQL grammY Docker


✨ Features

  • 💬 Telegram-first UX — add expenses and income through a conversational bot powered by grammY. No app to install.
  • 🗂️ Categories with emoji — organize spending and earnings into custom, emoji-tagged categories.
  • 🌍 Multi-currency — every entry is stored in its original currency and normalized to USD for unified reporting. The default currency is even inferred from the user's timezone.
  • 📊 Summaries & stats — instant breakdowns of where your money goes.
  • 🔐 Flexible auth — email/password, Google Sign-In, and Telegram login, with JWT access tokens and HTTP-only cookie refresh tokens.
  • 🪪 Plans & subscriptions — tiered limits (categories / expenses / incomes) baked into the data model.
  • 📚 Self-documenting API — Swagger UI generated automatically in non-production environments.
  • 🛡️ Hardened by default — request validation (Zod + class-validator), rate limiting (@nestjs/throttler), and CORS allow-listing.

🧱 Tech Stack

Layer Technology
Runtime Node.js + TypeScript
Framework NestJS 11 on Fastify
Telegram bot grammY
Database PostgreSQL via Prisma 7 ORM
Auth Passport + JWT, Google & Telegram strategies, bcrypt
Validation Zod (env) + class-validator / class-transformer (DTOs)
Tooling Biome (lint + format), Jest
Delivery Docker, Docker Compose, GitHub Actions → GHCR → VPS

🏗️ Architecture

                    ┌──────────────┐     webhook      ┌─────────────────────────┐
   Telegram  ◄─────►│  Telegram     │ ───────────────► │   NestJS + Fastify API   │
   user            │  (grammY bot)  │                  │                          │
                    └──────────────┘                  │  ┌────────────────────┐  │
                                                       │  │  Auth (JWT/Google/ │  │
   Web / API ◄────────── REST + Swagger ──────────────┤  │       Telegram)    │  │
   clients                                             │  ├────────────────────┤  │
                                                       │  │ Expenses / Incomes │  │
                                                       │  │ Categories         │  │
                                                       │  │ Currency / Summary │  │
                                                       │  │ Users / Plans      │  │
                                                       │  └────────────────────┘  │
                                                       └────────────┬─────────────┘
                                                                    │ Prisma
                                                                    ▼
                                                            ┌───────────────┐
                                                            │  PostgreSQL   │
                                                            └───────────────┘

The codebase is organized into feature modules under src/modules/ (auth, expenses, incomes, expense-categories, income-categories, currency, transactions, users), with the Telegram integration isolated in src/bot/ and shared utilities in src/common/.


🚀 Getting Started

Prerequisites

  • Docker & Docker Compose
  • A Telegram bot token (from @BotFather)
  • ngrok — Telegram webhooks require HTTPS, so ngrok tunnels your local server during development

1. Configure environment

Create a .env file in the project root:

PORT=3000
DATABASE_URL=postgresql://user:password@db:5432/limebalance

BOT_TOKEN=your-telegram-bot-token
WEBHOOK_URL=https://your-ngrok-subdomain.ngrok-free.app

CORS_ORIGIN=http://localhost:5173
GOOGLE_CLIENT_ID=your-google-client-id
JWT_SECRET=a-secret-of-at-least-32-characters

Environment variables are validated at startup against src/config/env.schema.ts — the app refuses to boot with an invalid configuration.

2. Run in development

make dev

This spins up the database and app via Docker Compose and starts an ngrok tunnel. Then point Telegram at your webhook:

make set-webhook

3. Apply database migrations

make migrate                       # create & apply during development
make migrate-create name=add_x     # create a named migration
make migrate-deploy                # apply pending migrations (production)
make migrate-status                # check migration state

Inspect data visually with Prisma Studio:

make db-studio   # http://localhost:5555

🧑‍💻 Local (non-Docker) workflow

npm install

npm run start:dev      # watch mode
npm run start:prod     # run compiled build from dist/

npm run lint           # Biome checks
npm run lint:fix       # Biome auto-fix
npm run format         # Biome format

npm run test           # unit tests
npm run test:e2e       # end-to-end tests
npm run test:cov       # coverage

📖 API Documentation

With the app running in a non-production environment, interactive Swagger docs are available at:

http://localhost:3000/api/docs

All routes are served under the /api prefix. A few highlights from the auth module:

Method Endpoint Description
POST /api/auth/register Register with email & password
POST /api/auth/login Log in and receive tokens
POST /api/auth/google Sign in with Google
POST /api/auth/telegram Sign in with Telegram
POST /api/auth/refresh Rotate the access token
GET /api/auth/me Get the current user
POST /api/bot/webhook Telegram webhook entry point

🚢 Deployment (CI/CD)

Pushing to the repository triggers the GitHub Actions workflow in .github/workflows/:

push ──► GitHub Actions
           ├── Builder stage     → compile TS → dist/
           └── Production stage  → dist/ + prod node_modules → ~150MB image
                                        │
                                        ▼
                            ghcr.io/<owner>/limebalance:latest
                                        │
                                        ▼
                            VPS: docker pull → docker run

The production image carries only the compiled output and runtime dependencies — no build toolchain — keeping it small and fast to ship.


📂 Project Structure

src/
├── bot/                  # Telegram bot: controller, service, state & handlers
│   └── handlers/         # start, expense, income, category, stat
├── common/               # currency/timezone utilities, shared DTOs
├── config/               # Zod-validated environment schema
├── modules/
│   ├── auth/             # JWT, Google & Telegram strategies, guards, decorators
│   ├── expenses/         # & expense-categories
│   ├── incomes/          # & income-categories
│   ├── currency/         # conversion & summary helpers
│   ├── transactions/
│   └── users/
├── prisma/               # Prisma service
└── main.ts               # bootstrap, CORS, validation, Swagger
prisma/                   # schema & migrations
scripts/                  # operational scripts (e.g. db backup)

📝 License

This project is currently private and unlicensed (UNLICENSED).

Built with NestJS, Prisma & grammY by Elijah Pavlov.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages