A full-stack, production-ready task management system built with Next.js 16 and Spring Boot 4. This project demonstrates enterprise-grade architecture, focusing on robust security, scalable state management, and a highly responsive user interface.
- Key Features
- Tech Stack
- Prerequisites
- Getting Started
- API Endpoints
- Architecture Highlights
- Screenshots
- Contributing
- License
- Author
- JWT Authentication: Short‑lived access tokens (15 mins) and long‑lived refresh tokens (7 days).
- Token Rotation & Reuse Detection: Prevents token theft by rotating refresh tokens and revoking entire token families if a token is reused.
- Token Blacklisting: Secure logout implementation using Redis to blacklist access tokens until expiration.
- Rate Limiting: Redis‑backed, thread‑safe rate limiting (Lua scripts) with smart tiers (Auth, Anonymous, Authenticated).
- Data Isolation: Strict owner‑only access control for private todos.
- Hybrid Rendering: Server‑Side Rendering (SSR) for SEO‑optimized public feeds and profiles, Client‑Side Rendering (CSR) for interactive dashboards.
- State Management: Zustand for lightweight, global client state (user session, UI modals).
- Server State: TanStack Query (React Query) for caching, background refetching, and optimistic UI updates.
- Modern UI/UX: Tailwind CSS v4, Lucide React icons, React Hot Toast notifications, and a custom top‑loading progress bar.
- Dynamic Routing: Beautiful user profile pages with dynamic metadata and SEO tags.
- Modular Architecture: Clean separation of Controllers, Services, Repositories, and DTOs.
- Database Migrations: Flyway for version‑controlled, reliable schema management.
- Soft Deletes: Data preservation using
deleted_attimestamps. - Dynamic Filtering: Spring Data JPA Specifications for complex, multi‑criteria searching and sorting.
- Dockerized Infrastructure: PostgreSQL and Redis managed via Docker Compose.
- Framework: Next.js 16 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS v4
- State Management: Zustand (Client), TanStack Query (Server)
- HTTP Client: Axios (with interceptors for auto‑refresh)
- Icons: Lucide React
- Framework: Spring Boot 4.1.1
- Language: Java 21
- Database: PostgreSQL 17.4
- Cache/Rate Limiting: Redis 7.4
- ORM: Spring Data JPA / Hibernate
- Security: Spring Security, JWT (jjwt), BCrypt
- Build Tool: Maven
Before you begin, ensure you have the following installed:
- Java 21 (or higher)
- Node.js 20+ (LTS recommended)
- Docker & Docker Compose (for Database and Redis)
- Maven (or use the included
mvnwwrapper)
git clone https://github.com/elamany/nextjs-springboot.git
cd nextjs-springbootStart Infrastructure (PostgreSQL & Redis):
cd backend
docker-compose up -dConfigure Environment:
Create a .env file in the backend directory:
DB_URL=jdbc:postgresql://localhost:5432/todo_db
DB_USERNAME=postgres
DB_PASSWORD=your_secure_password
JWT_SECRET=your_super_secret_jwt_key_at_least_256_bits
JWT_EXPIRATION_MS=900000
REFRESH_TOKEN_EXPIRATION_MS=604800000
Run the Backend:
./mvnw clean spring-boot:runThe backend will start on http://localhost:8080. Flyway will automatically run database migrations.
Install Dependencies:
cd frontend
npm installConfigure Environment:
Create a .env.local file in the frontend directory:
NEXT_PUBLIC_API_URL=http://localhost:8080/api/v1
Run the Frontend:
npm run devThe frontend will start on http://localhost:3000.
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
| POST | /api/v1/auth/register |
Register a new user | ❌ |
| POST | /api/v1/auth/login |
Login and get JWT tokens | ❌ |
| POST | /api/v1/auth/refresh |
Refresh access token | ❌ |
| POST | /api/v1/auth/logout |
Blacklist access token | ✅ |
| GET | /api/v1/todos/my |
Get current user's todos | ✅ |
| POST | /api/v1/todos |
Create a new todo | ✅ |
| PUT | /api/v1/todos/{id} |
Update a todo | ✅ |
| DELETE | /api/v1/todos/{id} |
Soft delete a todo | ✅ |
| GET | /api/v1/todos/public |
Get public todos (SSR) | ❌ |
| GET | /api/v1/users/{id} |
Get user profile (SSR) | ❌ |
| PUT | /api/v1/users/me |
Update current user profile | ✅ |
- User logs in → Backend returns
accessToken(15m) andrefreshToken(7d). - Frontend stores tokens in secure, HTTP‑only ready cookies.
- On API calls, Axios interceptor attaches the
accessToken. - If
401 Unauthorized, the interceptor automatically calls/auth/refresh. - Backend validates the refresh token, rotates it (issues a new one), and returns a new access token.
- If a refresh token is reused (indicating theft), the backend detects it and revokes the entire token family.
- Implemented using Redis and Atomic Lua Scripts to prevent race conditions.
- Tiers:
- 5 req/min for Authentication endpoints (brute‑force protection).
- 100 req/min for Anonymous users.
- 1000 req/min for Authenticated users.
- Login Page: Clean, validated authentication UI.
- Dashboard: Interactive todo list with filtering, pagination, and modals.
- Add Todo: Modal to create/add new todo's.
Contributions, issues, and feature requests are welcome! Feel free to check the issues page.
This project is licensed under the MIT License - see the LICENSE file for details.
Your Name
GitHub: @elamany
LinkedIn: My LinkedIn



