<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Emanuele Licata</title>
    <description>The latest articles on DEV Community by Emanuele Licata (@emalica).</description>
    <link>https://dev.to/emalica</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3895801%2F885434c7-acfd-4b44-9e18-9f530b068718.jpeg</url>
      <title>DEV Community: Emanuele Licata</title>
      <link>https://dev.to/emalica</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/emalica"/>
    <language>en</language>
    <item>
      <title>Building an Expenses Tracker API with NestJS — Back at It After a Break</title>
      <dc:creator>Emanuele Licata</dc:creator>
      <pubDate>Fri, 24 Apr 2026 10:14:48 +0000</pubDate>
      <link>https://dev.to/emalica/building-an-expenses-tracker-api-with-nestjs-back-at-it-after-a-break-3f95</link>
      <guid>https://dev.to/emalica/building-an-expenses-tracker-api-with-nestjs-back-at-it-after-a-break-3f95</guid>
      <description>&lt;p&gt;So I've been sitting on this project for a while.&lt;/p&gt;

&lt;p&gt;I started building an expenses tracker API a few months back, then uni got in the way and I kind of abandoned it. Classic. Now I'm picking it up again and I figured — why not document the journey publicly this time?&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is
&lt;/h2&gt;

&lt;p&gt;A REST API for tracking personal expenses. Built with NestJS and PostgreSQL, using Prisma as ORM and Argon2 for password hashing.&lt;/p&gt;

&lt;p&gt;The idea is to make it &lt;strong&gt;production-ready&lt;/strong&gt; — not just "it works on my machine" quality. JWT auth, Redis caching, Docker, Swagger docs, proper test coverage. The kind of backend you'd actually want to maintain.&lt;/p&gt;

&lt;p&gt;Also, I'll be honest: it's intentionally over-engineered for a personal finance app. The goal is the architecture, not the app itself. Portfolio project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it is right now
&lt;/h2&gt;

&lt;p&gt;Early stage. Like, &lt;em&gt;early&lt;/em&gt; early.&lt;/p&gt;

&lt;p&gt;What's working:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST /auth/signup&lt;/code&gt; — registers a user, hashes password with Argon2, stores in Postgres via Prisma&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /auth/signin&lt;/code&gt; — validates credentials, returns... a stub message for now 😅&lt;/li&gt;
&lt;li&gt;Global &lt;code&gt;ValidationPipe&lt;/code&gt; with whitelist — strips unexpected fields before they hit the service layer&lt;/li&gt;
&lt;li&gt;Duplicate email detection with a proper error response&lt;/li&gt;
&lt;li&gt;Docker Compose for the local dev database&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's &lt;strong&gt;not&lt;/strong&gt; working yet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JWT — the signin endpoint exists but doesn't return a token yet. &lt;code&gt;@nestjs/jwt&lt;/code&gt; isn't even installed. Next thing on the list.&lt;/li&gt;
&lt;li&gt;Basically everything else (expenses CRUD, categories, stats, budget tracking, Redis, CSV export...)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The stack
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NestJS v11 + TypeScript
PostgreSQL 16
Prisma v5
Argon2
Docker Compose
Jest + Supertest (tests: zero, for now)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;The immediate goal is finishing the auth flow — JWT access + refresh tokens, guards on protected routes, logout with token blacklist in Redis. Once that's solid I'll move on to the expenses CRUD.&lt;/p&gt;

&lt;p&gt;I'll try to post updates as I go. No promises on frequency though, still a student.&lt;/p&gt;



&lt;p&gt;If you've built something similar, I'd love to hear how you structured the auth module or whether you'd do anything differently with the stack. And if you're also working on a portfolio backend project — drop it in the comments, curious to see what others are building.&lt;/p&gt;

&lt;p&gt;Repo: &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/EmaLica" rel="noopener noreferrer"&gt;
        EmaLica
      &lt;/a&gt; / &lt;a href="https://github.com/EmaLica/expenses-api" rel="noopener noreferrer"&gt;
        expenses-api
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Expenses Tracker API&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;A personal finance tracking API built with NestJS and PostgreSQL. Designed both as a practical tool for managing personal expenses and as a showcase of serious backend architecture patterns.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Tech Stack&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;br&gt;
&lt;thead&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;br&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/thead&gt;
&lt;br&gt;
&lt;tbody&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;NestJS (v11)&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;PostgreSQL 16&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;ORM&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;Prisma (v5)&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;JWT + Argon2&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;Frontend &lt;em&gt;(planned)&lt;/em&gt;&lt;br&gt;
&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;Next.js / React&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;Caching &lt;em&gt;(planned)&lt;/em&gt;&lt;br&gt;
&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;Redis&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;tr&gt;
&lt;br&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;br&gt;
&lt;td&gt;Docker + VPS&lt;/td&gt;
&lt;br&gt;
&lt;/tr&gt;
&lt;br&gt;
&lt;/tbody&gt;
&lt;br&gt;
&lt;/table&gt;&lt;/div&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Implemented&lt;/h3&gt;

&lt;/div&gt;

&lt;ul class="contains-task-list"&gt;
&lt;li class="task-list-item"&gt;
 User registration (&lt;code&gt;POST /auth/signup&lt;/code&gt;) with email/password validation&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Password hashing with Argon2&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Duplicate email detection — Prisma P2002 → &lt;code&gt;403 ForbiddenException&lt;/code&gt;
&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 User signin (&lt;code&gt;POST /auth/signin&lt;/code&gt;) — credential lookup + Argon2 verify&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Global &lt;code&gt;ValidationPipe&lt;/code&gt; with whitelist (strips unexpected fields)&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Prisma ORM integration with PostgreSQL&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Database schema: &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;expenses&lt;/code&gt; tables with relations&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Expense table indexes on &lt;code&gt;userId&lt;/code&gt; and &lt;code&gt;date&lt;/code&gt; for query performance&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Docker Compose setup for local development database&lt;/li&gt;
&lt;li class="task-list-item"&gt;
 Empty module scaffolding: &lt;code&gt;UserModule&lt;/code&gt;, &lt;code&gt;ExpenseModule&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;In Progress&lt;/h3&gt;

&lt;/div&gt;


&lt;ul class="contains-task-list"&gt;

&lt;li class="task-list-item"&gt;

 JWT access token returned on signin (&lt;code&gt;@nestjs/jwt&lt;/code&gt;…&lt;/li&gt;

&lt;/ul&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/EmaLica/expenses-api" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>nestjs</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
