Bootstrapping a NestJS API for Personal Finance

The majority of NestJS tutorials available online tend to stop at basic CRUD operations or simple TODO list applications. Let’s move beyond these beginner examples and build something real and practical that you can actually use in production.

What We’re Building

We’re building a Personal Finance API from scratch. This series will guide you through creating a production-ready REST API to manage income, expenses,and accounts types—everything you need to track your money with confidence.

Each post is a 3–4 minute read focusing on one specific aspect of the application. By the end, you’ll have a fully functional API that you can extend or integrate with any frontend.

Architecture Overview

Our API will follow a modular, scalable architecture:

  • NestJS as our backend framework (TypeScript, dependency injection, decorators)

  • Supabase for PostgreSQL database hosting and authentication

  • Drizzle ORM for type-safe database queries and migrations

  • REST architecture with clear resource modeling

The application will be organized into feature modules:

  • auth: User authentication and authorization

  • accounts: account types: cash, debit, and credit

  • transactions: Income and expense tracking

  • categories: Transaction categorization

We’ll use semantic versioning throughout this series. For example, by the end of this post we’ll have v0.1.0. Minor changes like adding a constraint will bump to v0.1.1, and so on until we reach v1.0.0—a production-ready API.

This approach helps you break down large problems into manageable steps, making planning and execution much easier.

Setting Up the Project

Let’s bootstrap our NestJS application:

# Install the Nest CLI globally
npm i -g @nestjs/cli

# Create a new project
nest new finance-api

# Choose your preferred package manager (npm, yarn, or pnpm)

The CLI will generate a clean project structure with:

  • TypeScript configuration

  • Basic module, controller, and service

  • Testing setup with Jest

  • ESLint and Prettier configurations

Project Structure

After setup, we’ll organize our code following NestJS best practices:

src/
├── auth/             # Authentication module
├── accounts/         # Accounts module
├── transactions/     # Transactions module
├── categories/       # Categories module
├── common/           # Shared utilities, decorators, guards
│   ├── decorators/
│   ├── guards/
│   ├── interceptors/
│   └── filters/
├── config/           # Configuration module
├── database/         # Database connection and Drizzle setup
│   ├── migrations/
│   └── schema/
│   └── seeds/
├── app.module.ts
└── main.ts

Technical Decisions

Why Supabase?

Supabase provides:

  • Managed PostgreSQL database with automatic backups

  • Built-in authentication (email/password, OAuth, magic links)

  • Real-time subscriptions (optional for future features)

  • Auto-generated REST API (though we’ll build our own)

  • Free tier perfect for development

Why Drizzle ORM?

Drizzle offers:

  • Full TypeScript type safety without decorators

  • Lightweight and performant (faster than TypeORM)

  • SQL-like syntax that’s easy to learn

  • Migration system that’s version-control friendly

  • Perfect integration with NestJS’s modular architecture

Alternative considered: Prisma (great, but Drizzle gives us more control over queries and has better performance for complex relations).

We’ll discuss each of these tools in detail in their own posts. For now, this is a high-level overview of the project we’re building. At the end, you can use it as a guide and choose your preferred option.

Final thoughts

Here’s what you now have:

✅ A clean NestJS project ready for development

✅ Understanding of the overall architecture

✅ A clear folder structure to keep code organized

✅ Knowledge of why we chose Supabase and Drizzle

I know this post is simple, but we’re taking small steps to build gradually rather than rushing ahead. I hope this series serves as a guide for your future projects and gives you a framework for accomplishing those big goals.

Review the code so far at the link below:

🔗 Code: [GitHub repository]

💡 Next post: We’ll set up Supabase

Leave a Reply