Full Stack Case Study In Progress April 2026

Building an Insurance Management System:
Architecture First, Code Second

I am currently in the process of building a professional full stack insurance application: React, TypeScript, ASP.NET Core 10, PostgreSQL, layered architecture, JWT authentication, and EF Core, with a focus on doing it properly, not just making it work.

⚛️

Frontend

React + TypeScript + Tailwind

⚙️

Backend

ASP.NET Core 10 + C#

🗄️

Database

PostgreSQL + EF Core

🔐

Auth

JWT Bearer Tokens

The context

This project is a focused build of a full stack Insurance Management System, designed to reflect how real applications are structured and delivered. It brings together frontend, backend, and database concerns into a single cohesive system, with a strong emphasis on clean architecture and long term maintainability.

The goal is not just to build features, but to build them properly. Every part of the system is designed with intention, from how data flows through the application to how responsibilities are separated across layers. This is about building something that can scale and be clearly understood by other developers.

Why an insurance system?

The domain was chosen because of my past experience working in the insurance industry. It was always frustrating when a clients details were not always on one system. The project also naturally introduces meaningful relationships between entities. Clients, policies, and claims are connected in ways that require proper structure and logic. A client can have multiple policies, and each policy can have multiple claims. Those relationships directly influence how the system behaves, including things like risk calculation.

Building within a domain like this forces careful thinking around data modelling and system design. Instead of simple isolated features, the focus is on representing real world relationships accurately and ensuring the system remains consistent as it grows.

Architecture: the layered approach

The backend follows a structured layered architecture that separates concerns clearly across the application. Each layer has a defined responsibility and communicates with the next in a predictable way.

Request → Controller → Service → Repository → Database

Controllers handle routing and validation. Services contain business logic. Repositories handle data access. Keeping these responsibilities separate makes the system easier to understand, extend, and test.

Interfaces are defined first, with implementations registered through dependency injection in Program.cs. This keeps the system flexible and allows components to be swapped or extended without affecting other parts of the application.

Technology decisions

React Query over plain fetch

Data fetching on the frontend is handled using React Query. Instead of manually managing loading states, caching, and refetching logic, React Query provides a consistent and scalable way to work with server state.

This allows components to stay focused on rendering while data management is handled in a clean and predictable way.

PostgreSQL over SQLite

PostgreSQL is used as the database to reflect a production ready setup. It supports concurrent usage, strong data integrity, and more advanced querying capabilities than file based solutions.

Using a full database server ensures the system behaves more like a real deployed application from the start.

DTOs to separate concerns

The API is structured around Data Transfer Objects rather than exposing database models directly. Each operation has its own DTO, which keeps the API contract clear and avoids leaking internal structures.

Response DTOs also include computed values such as RiskLevel and TotalClaims, which are calculated within the service layer.

Tailwind CSS v4

The frontend uses Tailwind CSS v4, which keeps styling fast and simple. The setup is minimal, allowing styles to be applied directly without unnecessary configuration.

This keeps the focus on building the interface while maintaining a consistent design system.

Database design

The schema is built around four tables: Users, Clients, Policies, and Claims. These tables reflect the core structure of the system and how data is connected.

Entity Framework Core is used to generate and manage the database through migrations. The schema evolves directly from the C# models, keeping everything aligned.

// EF Core reads your C# class and creates the SQL table public class Policy { public int Id { get; set; } public string PolicyNumber { get; set; } = string.Empty; public decimal Premium { get; set; } public int ClientId { get; set; } // Foreign key public Client Client { get; set; } = null!; // Navigation property public ICollection<Claim> Claims { get; set; } = new List<Claim>(); }

Project setup and tooling

The project is structured as a monorepo with a clear separation between backend and frontend. Each part of the system is organised to keep responsibilities clear and easy to navigate.

The backend is organised into Controllers, Services, Repositories, Models, DTOs, and Data. This structure keeps the codebase clean and makes it easy to understand where logic belongs.

The frontend uses React Query, React Router, Axios, and Lucide React to handle data, routing, HTTP communication, and UI elements.

Sensitive values such as database connections and authentication keys are stored in environment specific files and excluded from version control.

What's coming next

The next phase focuses on expanding the service and controller layers, followed by building out the full frontend experience.

Authentication, risk calculation, and deployment will follow. The aim is to continue building out the system in a way that stays consistent with the architecture and keeps the codebase clean and understandable.

Follow the build

The full source code is on GitHub. More updates will be added as the project progresses.

View on GitHub
← Back to Blog