A Modern Angular + Spring Boot Template for human and AI-Assisted Development

A Modern Angular + Spring Boot  Template for human and AI-Assisted Development

TL;DR

I created a reusable Angular 22 and Spring Boot 4 template with Java 25, PostgreSQL, Flyway, OpenAPI, Docker, generated Angular API clients and project conventions that make the application easier to maintain by humans and AI coding agents.

Here you have the link: https://github.com/marco76/spring-angular-template

From basic to quality setup

In the last years I created many Angular + Java applications and I wanted to share the experience of the initial setup I created and updated some strategies: e.g.https://www.marmo.dev/deploy-java-angular-one/ at the time the problem was to find a suitable setup, the quick demo on YouTube had more than 10k views and many developers reached me asking help and information.

The goal at the time was to have an example of a basic architecture working. Maven was the orchestrator responsible to compile and build the different layers.

Now AI helps with this and we can go to the next step: build a startup template that is more powerful and it helps maintainig good standards and quality of the code. This is can be used by human developers or AI agents.

The goal is simple: start a professional Angular and Spring Boot application without losing the first hours or days on the same decisions every time and let it grow trying to maintain consistency and quality.

flowchart LR
    Browser["Browser"]

    subgraph Frontend["Angular"]
        UI["Standalone components"]
        AuthInterceptor["authCredentialsInterceptor"]
        ErrorInterceptor["httpErrorInterceptor"]
    end

    subgraph Backend["Spring Boot"]
        Security["Security filter chain"]
        Controllers["Controllers"]
        Services["Services"]
        Repos["Repositories"]
        ErrorHandler["GlobalExceptionHandler"]
    end

    DB[("PostgreSQL / H2")]

    Browser --> UI
    UI --> AuthInterceptor
    AuthInterceptor --> ErrorInterceptor
    ErrorInterceptor -- "/api/**" --> Security
    Security --> Controllers
    Controllers --> Services
    Services --> Repos
    Repos --> DB
    Controllers -. "exceptions" .-> ErrorHandler
    Security -. "access denied / unauthenticated" .-> ErrorHandler
    ErrorHandler -. "ApiError JSON" .-> ErrorInterceptor

No more a single JAR / WAR

The single fat JAR that contains Angular and Java presents many advantages, but the enterprise reality can require separate deployements (e.g. one frontend instance and multiple backend) or let the build pipeline create a Docker with the merge of the backend and frontend.
In the past we tried to have a full artifact, now with Kubernetes we tend to separate the layers. Build a fat JAR is simply an extra step.

With this architecture:
In development, Angular and Spring Boot can run separately. In Docker, Nginx serves the Angular build and proxies API calls to Spring Boot. PostgreSQL runs as its own service.

This is closer to what you probably see in production.

There is no universal best solution.

If your team deploys a single artifact to a Java application server, the one-JAR or WAR approach can be the correct one.

The stack

This template uses:

  • Angular 22
  • Angular Material
  • Standalone Angular components
  • Strict TypeScript
  • Spring Boot 4.1
  • Java 25
  • PostgreSQL
  • H2 for lightweight local development
  • Flyway migrations
  • Spring Security
  • Spring Validation
  • Spring Actuator
  • OpenAPI
  • A generated Angular API client
  • Docker and Nginx for the local production-like stack

The versions will be updated using the latest available versions.
Probably I'll use the latest Java even if it's not LTS ... change it if you want to use this template for a serious project.

Create a new project

From the template directory:

./create-project.sh invoice-hub com.acme.invoice ../invoice-hub

This creates a new project, replaces the Java package and application name, initializes Git, and installs the Angular dependencies.

You can also choose the initial UI and theme:

./create-project.sh invoice-hub com.acme.invoice ../invoice-hub --ui=basic
./create-project.sh invoice-hub com.acme.invoice ../invoice-hub --ui=minimal
./create-project.sh invoice-hub com.acme.invoice ../invoice-hub --theme=ft
./create-project.sh invoice-hub com.acme.invoice ../invoice-hub --theme=gl

The generated application includes three themes. The initial one can be selected when the project is created, and later changed from the admin page.

Run the application locally

The easiest local mode is Docker:

./scripts/deploy-local.sh up

This starts:

  • PostgreSQL
  • Spring Boot
  • Angular served by Nginx

Then open:

http://localhost:4200

The backend health endpoint is available here:

http://localhost:8080/actuator/health

For local development, there is also an interactive launcher:

./scripts/dev.sh

It can start:

  • the full Docker stack
  • Spring Boot with H2 and Angular dev server
  • Spring Boot against a local PostgreSQL and Angular dev server

The PostgreSQL mode is my favorite for serious development. It keeps the backend running natively with Spring Boot DevTools, but still uses a real PostgreSQL database.

docker compose up -d postgres
./scripts/dev.sh postgres

This gives a fast inner loop without pretending that H2 is PostgreSQL.

What is already included?

The template contains a small but useful application shell.

There is a home page, an admin page, HTTP Basic authentication for local development, database-backed users, and a basic admin user management UI.

The default local users are:

admin / admin
user / user

Of course, these are only local starter credentials. Replace them before using the project as the base for a real application.

The backend already follows a feature-based structure:

feature/
  FeatureController.java
  FeatureService.java
  db/
    FeatureRepository.java
    FeatureEntity.java
  model/
    FeatureResponse.java
  types/
    FeatureStatus.java

Controllers expose request and response models. Services own transactions and business decisions. Repositories and entities stay in the persistence layer.

This is not revolutionary, but it avoids the classic empty-project problem where the first real feature invents the architecture by accident.

API contract

The backend owns the API contract.

OpenAPI is generated from Spring Boot, and the Angular client is generated from that contract.

The rule is simple: Angular should not duplicate backend models manually.

When an endpoint changes:

./scripts/generate-api.sh

The generated Angular client is committed with the rest of the change, so the frontend can build without a running backend.

This is a choice, I usually see and prefer to have manually generated models, but sometimes the application is so complex that is simply not possible to do this. Again, we try to have an 'enterprise' template, the enterprise project is more restrictive than many internal projects.

The template also standardizes API errors. Spring Security errors, validation errors, and application errors use the same JSON shape, and Angular normalizes them in one interceptor.

Database migrations

Flyway owns the schema.

Migrations live here:

backend/src/main/resources/db/migration

Example:

V1__initial_schema.sql
V2__create_app_user.sql

Local sample data and automated test fixtures are kept separate from schema migrations. This is important. A migration should describe the database structure, not silently inject local development data into production.

Built for AI-assisted development

This template also includes something I now consider important: instructions for coding agents.

There are architecture notes, conventions, project state, API contract documentation, and task checklists under .agent/tasks.

The idea is that your Agent will try to follow these instructions, but don't trust them the result is not deterministic, you will need to read the generated result and validate it.

We try to explain AI agent what kind of architecture we want. Which package structure should be used? Where do DTOs live? How are migrations named? When should the OpenAPI client be regenerated? Which checks must run before a change is done?

Without these rules, agents improvise. Sometimes they improvise well. Sometimes they create a small museum of technical debt.

With explicit rules, they become much more predictable.

I added ArchUnit to do a static check of the generated code structure. You can easily add your own rules. This is another quality check to be sure that the developer (human or not) follows the design.

Checks

The template includes scripts for the usual verification steps:

./scripts/check-backend.sh
./scripts/check-frontend.sh
./scripts/check.sh
./scripts/smoke.sh
./scripts/doctor.sh

doctor.sh is especially useful after generating a new project. It checks for leftover placeholders, required tooling, and common setup problems.

Optional MCP support

There is optional Spring AI / MCP support, but it is disabled by default.

This is intentional to avoid exposing runtime MCP endpoints without authentication.

If you need it:

./create-project.sh invoice-hub com.acme.invoice ../invoice-hub --mcp

Then read the MCP setup documentation before exposing anything.

Which AI Agent?

I tried to have a template that is generic enough to be used with the most common AI agent. Claude plays with its own rules for this reason there is a re-direct that should help the multi AI compatibility and avoid the duplication of the instructions.
Spring Tools MCP plugin is currently compatible only with Claude, it won't work with other AI agents.

Which IDE?

Technically you don't need an IDE to use the template, but there are some optimisations prepared for IntellJ IDEA (e.g. shortcut starter).

Conclusion

This is a starting point for a new project without re-inventing the wheel each time. I didn't use it often, it was a small project for a demo. I will try to improve it with the latests AI discoveries.

I'm thinking to add some features like WebSockets, file uploads, OAuth, CI/CD and Kubernetes. I use these features in real-world project, but I know that many project simply don't need them.