Enterprise SaaS Starter

May 12, 2026 Β· View on GitHub

Version Java Spring Boot Angular MSSQL Docker License Website

A production-ready fullstack boilerplate for building SaaS applications β€” Java 21 + Spring Boot 3.4.1 backend, Angular 21 frontend, MSSQL database, fully containerized with Docker Compose. Clone, configure, and ship.

🌐 Full Features & Live Demo: zukovlabs.com
⭐ Found this useful? Drop a star β€” it helps other Java developers find this project.


See the PRO Version in Action (2-minute Demo)

Watch the Demo β–Ά Click to watch the full walkthrough on YouTube

Table of Contents


⚑ Upgrade to PRO

Skip 200+ hours of engineering work.

The Community Edition gives you a solid foundation. The PRO version ships everything you need to launch a real, monetized SaaS product β€” without building it from scratch.

What you get with PRO that you cannot build in a weekend:

AreaWhat PRO Delivers
PaymentsFull Stripe integration: Checkout Sessions, Webhook handling with signature verification, Billing Portal, and automatic post-payment login via Magic Link
Passwordless AuthMagic Link (one-time email links, 15-min TTL) β€” a proven conversion booster for SaaS onboarding
Email ServiceThymeleaf HTML email templates: welcome, magic link, payment success β€” production-ready and styled
SecurityIP-based sliding-window rate limiter on all auth endpoints β€” brute-force and flood protection
Data LayerServer-side pagination (Spring Pageable + MatPaginator) β€” Community Edition loads all rows client-side; PRO paginates at the database level for scale
Access ControlStrict RBAC with three roles (ADMIN / MANAGER / USER) enforced via @PreAuthorize at the method level
Multi-TenancyEntity ownership enforcement β€” users can only see and delete their own records. 403 FORBIDDEN if violated
Signal CachingAngular signal<T> cache in services β€” two components, one HTTP request
Test Suite13 test files, 88 cases: Mockito strict stubs, ArgumentCaptor assertions, Vitest frontend tests, real ObjectMapper for Stripe JSON fallback path

The math is simple:

  • Payments: Stripe integration (webhooks, billing portal, edge cases): ~40 hours
  • Auth & Comms: Magic Link logic, Email Service, Thymeleaf templates: ~40 hours
  • Security & Core: Rate limiting, strict RBAC, data ownership (403): ~40 hours
  • Frontend UX: Dashboard charts, Server-side pagination, Signal Cache: ~40 hours
  • Quality Assurance: 88 strict test cases, Mockito, Vitest: ~40 hours
  • Total: 200+ hours of deep engineering β€” or one license purchase.

πŸ‘‰ Get PRO Version β€” €149 one-time β†’


Free vs. PRO Comparison

FeatureCommunity (Free)PRO
Java 21 + Spring Boot 3.4.1βœ…βœ…
Angular 21 Standalone Componentsβœ…βœ…
MSSQL 2022 + Flyway Migrationsβœ…βœ…
Multi-stage Docker Buildsβœ…βœ…
Nginx SPA Hosting + Security Headersβœ…βœ…
MSSQL Healthcheck (no startup race)βœ…βœ…
JWT Auth (Access + Refresh Tokens)βœ… Basicβœ… Enhanced
Refresh Token Rotationβœ…βœ…
BCrypt Password Hashingβœ…βœ…
User Profile Managementβœ…βœ…
Basic Customer CRUDβœ…βœ…
Dashboard Stats APIβœ…βœ…
Angular Material UIβœ…βœ…
401 Race Condition Protection (Interceptor)βœ…βœ…
Auth Guard (JWT exp validation + redirect)βœ…βœ…
β€”β€”β€”
Stripe Checkout + Webhook HandlingβŒβœ…
Stripe Billing Portal (self-service)βŒβœ…
Magic Link (Passwordless Auth)βŒβœ…
Post-Payment Auto-Login via Magic LinkβŒβœ…
Email Service (Thymeleaf HTML templates)βŒβœ…
IP Rate Limiting (brute-force protection)βŒβœ…
Server-Side Pagination (Spring Pageable backend + MatPaginator)βŒβœ…
Strict RBAC (ADMIN / MANAGER / USER)βŒβœ…
Entity Ownership Enforcement (403)βŒβœ…
Signal Cache (no duplicate HTTP calls)βŒβœ…
Dashboard Charts (Chart.js)βŒβœ…
13 Test Files / 88 Test CasesβŒβœ…
Mockito Strict Stubs + ArgumentCaptorβŒβœ…
Vitest Frontend Test SuiteβŒβœ…
Fail-Fast JWT Secret ValidationβŒβœ…
Commercial Use Licenseβœ… MITβœ… Commercial

πŸ‘‰ Upgrade to PRO β†’


Overview

The Community Edition is a clean, runnable fullstack starting point β€” no toy demo, no half-implemented code. It ships with:

  • Stateless JWT authentication with access and refresh token rotation
  • Basic Customer CRM β€” create, list, and delete customer records
  • User profile management β€” update name and change password
  • Dashboard stats endpoint β€” aggregate data from the backend
  • One-command Docker deploy β€” docker compose up -d --build starts the entire stack
  • Nginx-served Angular SPA with /api/* proxy to the Spring Boot backend, gzip compression, and security headers
  • It compiles successfully, passes standard health checks, and provides a secure starting point.

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Docker Compose                   β”‚
β”‚                                                    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  MSSQL   │───▢│  Spring Boot  │◀───│  Nginx  β”‚  β”‚
β”‚  β”‚  :1433   β”‚    β”‚    :8080      β”‚    β”‚  :8081  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜  β”‚
β”‚   healthcheck      Flyway migrations        β”‚       β”‚
β”‚   passes first     on startup           Angular SPA β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β–²
                    Browser Client

Request flow:

Request β†’ JwtAuthenticationFilter β†’ SecurityConfig rules β†’ Controller β†’ Service β†’ Repository

Tech Stack

ComponentTechnologyVersion
LanguageJava21 LTS
FrameworkSpring Boot3.4.1
SecuritySpring Security6.x
ORMHibernate / JPAβ€”
JWTJJWT0.12.3 (HS512)
MigrationsFlywayβ€”
Build ToolMaven3.9.6
FrontendAngular21 (Standalone)
UI LibraryAngular Material21
ReactiveRxJS7.8
DatabaseMSSQL Server2022
ContainerizationDocker + Composeβ€”
Web ServerNginxAlpine

Prerequisites

Install these before you start:

ToolPurposeMin Version
Docker DesktopRun the full stackLatest
Java 21 JDKLocal backend development21 LTS
Node.jsLocal frontend development20+

Getting Started

1. Clone the Repository

git clone https://github.com/zukovlabs/enterprise-java-saas-starter-kit.git
cd enterprise-java-saas-starter-kit

2. Configure Environment Variables

Copy the example file and set your values:

copy .env.example .env

Open .env and set at minimum:

JWT_SECRET=your-256-bit-hex-secret-here
DB_PASSWORD=YourStrongPassword1!
CORS_ALLOWED_ORIGINS=http://localhost:8081

Generate a strong JWT secret: openssl rand -hex 32

3. Start the Stack

docker compose up -d --build

Docker Compose will:

  1. Start the MSSQL container and wait for the healthcheck to pass
  2. Start the Spring Boot backend β€” Flyway migrations run automatically on startup
  3. Start the Angular frontend served via Nginx

4. Open the Application

ServiceURL
Frontendhttp://localhost:8081
Backend APIhttp://localhost:8080
Databaselocalhost:1433

5. Log In with the Demo Accounts

Flyway seeds two accounts on first startup:

EmailPasswordRole
admin@saaskit.comAdmin1234!ADMIN
user@saaskit.comUser1234!USER

6. Useful Commands

# Watch backend logs
docker compose logs -f backend

# Stop the stack
docker compose down

# Stop and remove volumes (fresh DB)
docker compose down -v

# Rebuild a single service
docker compose up -d --build backend

7. Local Development (Optional)

If you want to edit the code with full IDE support (IntelliSense, types), you should install the dependencies locally on your host machine:

Frontend:

cd frontend
npm install
npm start # runs Angular dev server on http://localhost:4200

Environment Variables

All variables are sourced from the .env file (see .env.example for a full template with comments).

VariableRequiredDefaultDescription
APP_URLβœ…http://localhost:8081Base URL of the application
JWT_SECRETβœ…β€”256-bit hex string for HS512 signing
JWT_EXPIRATION_MSβ€”86400000 (24h)Access token TTL in milliseconds
JWT_REFRESH_EXPIRATION_MSβ€”604800000 (7d)Refresh token TTL in milliseconds
DB_PASSWORDβœ…StrongP@ssw0rd!MSSQL SA account password
CORS_ALLOWED_ORIGINSβœ…http://localhost:4200,http://localhost:8081,http://localhostComma-separated allowed CORS origins

Database & Migrations

Schema is managed by Flyway β€” migrations run automatically on every backend startup.

Migration files: src/main/resources/db/migration/

FileDescription
V1__init_schema.sqlCreates users and customers tables. Seeds two demo accounts and sample customers. Refresh tokens are stateless JWTs β€” no database table required.

Default development credentials:

FieldValue
Hostlocalhost:1433
Usersa
PasswordStrongP@ssw0rd! (override via DB_PASSWORD)
Databasemaster

Note: Demo accounts seeded by Flyway use {noop} plain-text passwords for developer convenience. All passwords created via /api/auth/register are BCrypt-encoded automatically.


API Reference

Authentication β€” /api/auth

MethodEndpointAuthDescription
POST/api/auth/registerβ€”Register a new user
POST/api/auth/loginβ€”Login, returns accessToken + refreshToken
POST/api/auth/refreshβ€”Rotate tokens using a valid refresh token

Login response:

{
  "token": "eyJ...",
  "refreshToken": "eyJ..."
}

All subsequent requests must include:

Authorization: Bearer <token>

Users β€” /api/user

MethodEndpointAuthDescription
GET/api/user/profileβœ…Get the authenticated user's profile
PUT/api/user/profileβœ…Update first name and last name
PUT/api/user/passwordβœ…Change password (requires current password)

Customers β€” /api/customers

MethodEndpointAuthDescription
GET/api/customersβœ…List all customers
POST/api/customersβœ…Create a new customer
DELETE/api/customers/{id}βœ…Delete a customer by ID

Dashboard β€” /api/dashboard

MethodEndpointAuthDescription
GET/api/dashboard/statsβœ…Get aggregate stats (total and active customer counts)

Project Structure

enterprise-saas-starter-core/
β”‚
β”œβ”€β”€ src/main/java/com/saaskit/starter/
β”‚   β”œβ”€β”€ SaasApplication.java            # Spring Boot entry point (@SpringBootApplication)
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”œβ”€β”€ ApplicationConfig.java      # Auth provider, password encoder, UserDetailsService
β”‚   β”‚   └── SecurityConfig.java         # Filter chain, CORS, public vs. protected endpoints
β”‚   β”‚
β”‚   β”œβ”€β”€ controller/
β”‚   β”‚   β”œβ”€β”€ AuthController.java         # /api/auth/** (register, login, refresh)
β”‚   β”‚   β”œβ”€β”€ CustomerController.java     # /api/customers (list, create, delete β€” calls repository directly)
β”‚   β”‚   β”œβ”€β”€ DashboardController.java    # /api/dashboard/stats (calls repository directly)
β”‚   β”‚   └── UserController.java         # /api/user/** (profile, password)
β”‚   β”‚
β”‚   β”œβ”€β”€ service/
β”‚   β”‚   β”œβ”€β”€ AuthService.java            # Registration, login, JWT refresh logic
β”‚   β”‚   └── UserService.java            # Profile & password management
β”‚   β”‚
β”‚   β”œβ”€β”€ repository/
β”‚   β”‚   β”œβ”€β”€ UserRepository.java
β”‚   β”‚   └── CustomerRepository.java
β”‚   β”‚
β”‚   β”œβ”€β”€ model/
β”‚   β”‚   β”œβ”€β”€ User.java                   # User entity (email, password, role)
β”‚   β”‚   └── Customer.java               # Customer entity
β”‚   β”‚
β”‚   β”œβ”€β”€ dto/                            # Java Records β€” validated request/response DTOs
β”‚   β”‚   β”œβ”€β”€ LoginRequest.java
β”‚   β”‚   β”œβ”€β”€ RegisterRequest.java
β”‚   β”‚   β”œβ”€β”€ AuthResponse.java
β”‚   β”‚   β”œβ”€β”€ DashboardStats.java
β”‚   β”‚   β”œβ”€β”€ UpdateProfileRequest.java
β”‚   β”‚   └── ChangePasswordRequest.java
β”‚   β”‚
β”‚   └── security/
β”‚       β”œβ”€β”€ JwtUtils.java               # HS512 token generation, parsing, expiry check
β”‚       └── JwtAuthenticationFilter.java# Extracts + validates JWT, sets SecurityContext
β”‚
β”œβ”€β”€ src/main/resources/
β”‚   β”œβ”€β”€ application.yml                 # Full configuration (environment-variable driven)
β”‚   └── db/migration/
β”‚       └── V1__init_schema.sql         # Schema creation + demo data seed
β”‚
β”œβ”€β”€ src/test/java/                      # Backend unit tests (JUnit 5 + Mockito)
β”‚
β”œβ”€β”€ frontend/
β”‚   β”œβ”€β”€ src/app/
β”‚   β”‚   β”œβ”€β”€ pages/
β”‚   β”‚   β”‚   β”œβ”€β”€ landing/                # Public marketing / home page
β”‚   β”‚   β”‚   β”œβ”€β”€ login/                  # Email + password login form
β”‚   β”‚   β”‚   β”œβ”€β”€ register/               # Registration form
β”‚   β”‚   β”‚   β”œβ”€β”€ dashboard/              # Stats overview page
β”‚   β”‚   β”‚   β”œβ”€β”€ customers/              # Customer list + create/delete
β”‚   β”‚   β”‚   β”‚   └── customer-dialog/    # Add-customer dialog component
β”‚   β”‚   β”‚   └── settings/               # Profile & password management
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”‚   β”œβ”€β”€ auth.service.ts         # Login, register, refresh, logout
β”‚   β”‚   β”‚   β”œβ”€β”€ user.service.ts         # Profile CRUD
β”‚   β”‚   β”‚   β”œβ”€β”€ customer.service.ts     # Customer API calls
β”‚   β”‚   β”‚   └── dashboard.service.ts    # Stats API call
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”‚   └── confirm-dialog/         # Reusable confirmation dialog
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ layout/main-layout/         # App shell: sidebar + header
β”‚   β”‚   β”œβ”€β”€ models/                     # TypeScript interfaces (customer, dashboard-stats)
β”‚   β”‚   β”œβ”€β”€ auth.guard.ts               # Checks token presence in localStorage before route activation
β”‚   β”‚   └── auth.interceptor.ts         # Injects Bearer token + handles 401 with token refresh
β”‚   β”‚
β”‚   β”œβ”€β”€ nginx.conf                      # SPA routing, /api reverse proxy, gzip, security headers
β”‚   └── Dockerfile                      # Multi-stage: Node 20 β†’ Nginx Alpine
β”‚
β”œβ”€β”€ Dockerfile                          # Multi-stage: Maven 3.9.6 + JDK 21 β†’ JRE 21 Alpine
β”œβ”€β”€ compose.yaml                        # DB (healthcheck) β†’ Backend β†’ Frontend
β”œβ”€β”€ .env.example                        # All variables with descriptions
└── pom.xml                             # Maven dependencies

Want More? Upgrade to PRO

The Community Edition is intentionally minimal. The PRO version is what you actually ship to customers.

PRO adds:

  • Stripe payments (Checkout, Webhooks, Billing Portal)
  • Magic Link passwordless authentication
  • HTML email service with Thymeleaf templates
  • IP rate limiting on auth endpoints
  • Server-side pagination (no full-table loads)
  • Strict three-tier RBAC (ADMIN / MANAGER / USER)
  • Entity ownership enforcement with 403 responses
  • Angular Signal cache (zero duplicate HTTP calls)
  • Dashboard charts with Chart.js
  • 13 test files, 88 cases β€” Mockito strict stubs, Vitest frontend, ArgumentCaptor assertions

πŸ‘‰ See full details at zukovlabs.com β†’


Contributing

Contributions, bug reports, and feature requests are welcome. Open an issue or submit a pull request.


Support & Questions

Have a question, found a bug, or need help?


License

This project is licensed under the MIT License β€” free to use, modify, and distribute. See LICENSE for details.

Enterprise SaaS Starter PRO is a separate commercial product with its own license terms.


Built by ZukovLabs