DEV Community

Cover image for Building a Full-Stack Bookkeeping Ledger Using Antigravity
Rohith V
Rohith V

Posted on

Building a Full-Stack Bookkeeping Ledger Using Antigravity

I recently built a full-stack bookkeeping application to help track borrowed money and loan repayments. My goal for this side project was to build a secure, practical tool from scratch while gaining hands-on experience with modern, decoupled application architecture. I usually lend money, and most of the time, I get lost in tracking the records.

Since we have modern AI agents and tools, I use Google Antigravity IDE, where my primary focus was to provide the requirements, review the plan put forward by Antigravity, review the code, and provide suggestions.

Here is an overview of the project, the tech stack I used, and some of the technical challenges I solved along the way.

The Tech Stack

I chose to separate the frontend from the backend to mirror how production applications are often built. The project is hosted entirely on cloud-free tiers.

  • Backend: Java, Spring Boot 3, Spring Data JPA
  • Database: PostgreSQL (hosted on Neon.tech)
  • Frontend: Vanilla JavaScript, HTML, and CSS
  • Security: Spring Security 6 with stateless JWTs
  • Deployment: Render (Backend), GitHub Pages (Frontend), with GitHub Actions for CI/CD
  • IDE: Google Antigravity

Core Features

The application handles standard CRUD operations for managing borrowers and tracking active loans. However, I focused heavily on building out two specific areas: security and realistic repayment logic.

1.Partial Repayment Logic
Instead of just marking a loan as "paid" or "unpaid", I implemented an endpoint that allows for partial repayments.

When a user submits a repayment amount, the Spring Boot backend processes the math. If the remaining balance drops to zero or below, the program automatically deletes the loan record from the PostgreSQL database. If there is still a remaining balance, it securely updates the active record.

2.Stateless Security and JWTs
To secure the API, I implemented stateless authentication using JSON Web Tokens (JWT). Instead of storing the token in local storage, where it might be exposed to XSS attacks, the backend packages it in an HttpOnly cookie.

3.Handling Cross-Origin Requests
One of the main challenges of deploying a decoupled app is dealing with browser security policies. Because the frontend is hosted on GitHub Pages and the backend is on Render, the domains do not match.

By configuring the server only to accept JSON payloads and explicitly whitelisting the GitHub Pages domain, the browser's native preflight OPTIONS requests successfully neutralize CSRF threats without relying on third-party cookies.

4.Brute-Force Protection
To protect the database from automated login attacks, I integrated Bucket4j into the authentication flow. This acts as an API rate limiter, restricting users to a maximum of 5 login attempts per minute before temporarily blocking their IP.

Repository and Deployment

To ensure the project remains stable, I set up a GitHub Actions pipeline that automatically runs my JUnit and Mockito integration tests on every push.

You can view the source code and the live deployment here:

GitHub Repository:

GitHub logo Rohithv07 / BookKeeping

Record the debts that we are lending to other people.

BookKeeping

Record the debts that we are lending to other people.

What was implemented

  1. Spring Boot App: A robust REST API running on Java 21, built using Gradle.
  2. Database Models
    • Borrower: Saves name, email, and phone.
    • Loan: Tracks amount, date lent, exact 1-month (dueDate), and loan status (ACTIVE vs REPAID).
  3. Core API Endpoints
    • POST /api/borrowers and GET /api/borrowers
    • POST /api/loans and GET /api/loans
    • PUT /api/loans/{id}/repay
  4. Notification Job: The NotificationService is scheduled to run every day at 8:00 AM. It queries the database for any active loans where the due date is today or earlier and dispatches an email exclusively to your personal Gmail account (as requested).
  5. System Architecture Upgrades
    • Interface-Driven Design: The Service layer employs interface contracts (BorrowerService, LoanService) for loose coupling and scalability.
    • Data Transfer Objects (DTOs): API payloads exclusively use BorrowerDto and…

Live Application: https://rohithv07.github.io/BookKeeping/

Please note that the app will be slow as all the deployments are with limited resources and a free tier.

Top comments (0)