Skip to main content

PROJECT CASE STUDY · FULL-STACK ARCHITECTURE

MAD AI

An administrative web application with an Angular 20 client and a separately maintained private Django 5.2 API, covering authentication, user and role management, notifications and reporting.

Mixed source Maintained

SYSTEM BOUNDARY

A public Angular client and a separately maintained private API

MAD AI is split across two repositories. The Angular client contains the SSR entry point, routed administrative UI, explicit client-side layers and HTTP adapters. A separate Django REST service owns backend application and persistence concerns. The repositories can evolve independently while meeting at the REST contract.

PROBLEM

Administrative workflows accumulate cross-cutting concerns quickly

Authentication, guarded navigation, user administration, roles, notifications and reporting all need shared application behavior without turning routed components into transport clients. The project separates those concerns at both ends: an Angular client with explicit layers and a Django REST service with its own application/domain/infrastructure boundaries.

SYSTEM

Two repositories, two independent architectural boundaries

MAD AI current system boundary. The Angular 20 client renders through browser or SSR and calls a separately maintained Django 5.2 REST API. The backend uses DRF/JWT-oriented adapters and PostgreSQL support; Celery is present for asynchronous work.

FRONTEND

Layer names correspond to real Angular boundaries

DOMAIN

CONTRACTS BEFORE TRANSPORT

Domain entities and repository abstractions define what authentication, users, roles and notifications need without embedding endpoint details into routed components.

APPLICATION

USE CASES COORDINATE INTENT

Application code sits between presentation and infrastructure so UI flows express actions through use cases instead of binding every component directly to HTTP mechanics.

INFRASTRUCTURE

HTTP REPOSITORIES ADAPT THE API

Concrete implementations for authentication, notifications, roles and users own DTO/API interaction behind repository contracts. Environment configuration points those adapters to /api/v1.

PRESENTATION

ROUTES DEFINE PUBLIC AND SECURED AREAS

Authentication routes use their own layout, while dashboard and user-management surfaces sit behind AuthGuard inside the secured shell. Angular SSR and Express provide the server-rendered entry path.

BACKEND

The API uses a pragmatic modular Django architecture

The backend uses Django 5.2.3 and Django REST Framework 3.16.0, with JWT/cryptography support, PostgreSQL through psycopg2, filtering, OpenAPI tooling and Celery. Its architecture combines a service layer, domain-centric Django models and ports/adapters rather than forcing a framework-neutral domain that duplicates the ORM.

The API is maintained in a private repository, making the REST contract the explicit boundary between the open client and backend implementation. Presentation and interaction remain client responsibilities; application orchestration and persistence stay behind the API.

REPORTING

The client owns visualization and export concerns

The Angular client includes ECharts, jsPDF and PapaParse. Keeping charting and export libraries in the client lets reporting surfaces transform API responses into interactive visualizations and downloadable representations without pushing presentation concerns back into the REST service.

CURRENT IMPLEMENTATION

Responsibilities remain explicit across client and API

CLIENT

ANGULAR 20 · SSR · EXPRESS 5 · TAILWIND 4

The Angular client uses Angular 20, Angular SSR, Express 5, RxJS and Tailwind CSS 4. Its code separates domain, application, infrastructure and presentation, with guarded routes and concrete HTTP repository implementations.

API

DJANGO 5.2 · DRF 3.16 · JWT · POSTGRESQL · CELERY

The companion API uses Django 5.2.3 and DRF 3.16 with JWT/cryptography, PostgreSQL support and Celery. It remains a private service maintained separately from the public client.

ACTIVE BOUNDARY

REQUEST/RESPONSE REST IS THE CURRENT TRANSPORT

The maintained backend does not include Django Channels, so WebSocket behavior is outside the current system flow. Client and API integration is centered on the REST contract.

DELIVERY BOUNDARY

CLIENT AND API CAN EVOLVE INDEPENDENTLY

The split keeps presentation and backend delivery concerns separate. Changes on either side need to preserve the shared REST contract rather than requiring both repositories to share implementation details.

LEARNINGS

What the two-repository design reinforced

LEARNING 01

CLIENT ARCHITECTURE CAN HAVE REAL BOUNDARIES

A frontend can separate domain intent from HTTP adapters instead of treating every component as a wrapper around an endpoint.

LEARNING 02

FRAMEWORK-PRAGMATIC CLEAN BOUNDARIES CAN BE STRONG

Django models can remain rich domain entities while services and repository ports protect orchestration and external adapters; clean architecture does not require fighting the framework.

LEARNING 03

REPOSITORY BOUNDARIES SHOULD MATCH SYSTEM BOUNDARIES

Keeping client contracts separate from backend implementation details reduces coupling between repositories and makes ownership of presentation, transport and persistence responsibilities clearer.