This codebase adopts a decoupled architecture composed of complementary services:
| Service | Stack | Purpose | Default Port |
|---|---|---|---|
| Frontend | Next.js (React, TypeScript) | User interface, routing, client state management | 3000 |
| Backend | Spring Boot (Java 21) | Business logic, validation, persistence, security | 8080 |
- Frontend: Next.js application providing the user interface, routing, and client-side state management.
- Backend: Spring Boot REST API responsible for business logic, validation, persistence, and security.
During development the frontend runs on http://localhost:3000 and communicates with the backend on http://localhost:8080 via HTTP.
Architecture Snapshot: The frontend communicates with the backend exclusively through REST endpoints. CORS and Spring Security enforce a clean boundary between presentation and domain logic.
-
Clone and enter the repository
git clone https://github.com/maydaythecoder/NextJS-Spring-Boot cd NextJS-Spring-Boot -
Install dependencies
./backend/mvnw dependency:resolve (cd frontend && npm install) -
Prepare environment files
cp backend/env.example backend/.env.local cp frontend/env.example frontend/.env.local
Adjust the copied files if you need non-default ports or database credentials.
-
Launch both services
chmod +x run.sh ./run.sh
-
Verify endpoints
- Frontend:
http://localhost:3000 - API:
http://localhost:8080/users
- Frontend:
.
├── backend/
│ ├── mvnw, mvnw.cmd
│ ├── pom.xml
│ └── src/
│ ├── main/
│ │ ├── java/com/example/tutorial/
│ │ │ ├── TutorialApplication.java
│ │ │ ├── api/UserController.java
│ │ │ ├── config/{CorsConfig.java, SecurityConfig.java}
│ │ │ ├── model/User.java
│ │ │ └── service/UserService.java
│ │ └── resources/application.properties
│ └── test/java/com/example/tutorial/TutorialApplicationTests.java
├── frontend/
│ ├── package.json, package-lock.json
│ ├── next.config.ts
│ ├── src/
│ │ ├── app/
│ │ │ ├── layout.tsx
│ │ │ ├── page.tsx
│ │ │ └── users/{page.tsx,[id]/page.tsx,new/page.tsx,...}
│ │ ├── components/{common/,users/}
│ │ ├── lib/{api/,hooks/,state/,types/}
│ │ └── app/globals.css
│ └── tsconfig.json
├── run.sh
└── .gitignoreTutorialApplication.java: Spring Boot entry point.api/UserController.java: Defines CRUD endpoints for/users.service/UserService.java: In-memory user store and business logic.config/CorsConfig.java: Configures CORS to allow the frontend origin.config/SecurityConfig.java: Spring Security filter chain configuration.
layout.tsx: Global layout with shared navigation and fonts.users/: App Router segments for listing users, viewing details, and creating records.components/common/: Reusable UI primitives (navbar, error states, etc.).components/users/: User-specific cards, skeletons, and forms.lib/api/: Fetch utilities encapsulating backend interaction.lib/hooks/: Custom React hooks for form state and API integration.
- Frontend components call the backend via
fetchwrappers defined insrc/lib/api/users.ts. - Hooks (for example
useCreateUserForm) encapsulate mutation flows and local state updates. - The backend exposes REST endpoints for retrieving, creating, updating, and deleting users.
- Spring Security disables form login and HTTP Basic, exposing open endpoints for now.
- The security filter chain is ready for future authentication mechanisms (JWT, OAuth2, session-based).
- CORS configuration restricts requests to the known frontend origin.
- Backend controllers can leverage Spring validation annotations to enforce input requirements.
- Frontend forms perform basic client-side validation prior to submitting requests.
- User interacts with the Next.js UI (e.g., visiting
/usersor submitting the creation form). - Frontend hook issues an HTTP request to the Spring Boot API (
GET/POST/PUT/DELETE /users). - Controller delegates to
UserService, which manages the in-memory store (or database when extended). - Service returns results to the controller, which serializes them as JSON responses.
- Frontend receives the JSON payload and updates component state to render the latest data.
- CORS: Allows requests only from
http://localhost:3000during development. - CSRF: Disabled to simplify API usage; add token-based safeguards when introducing browser sessions.
- Headers: Frame options relaxed exclusively for the H2 console; other default headers remain intact.
- Future Authentication: Security configuration is structured to plug in real authentication and role-based rules.
- Validation: Extend service/controller layers to enforce strict input validation and sanitize logs.
- Node.js 20+
- npm 10+
- Java 21+
- Maven Wrapper (bundled) or Maven 3.9+
# Backend
cd backend
./mvnw dependency:resolve
# Frontend
cd ../frontend
npm installCreate the following environment files before running the application. Sample templates are provided at backend/env.example and frontend/env.example.
cp backend/env.example backend/.env.local # adjust values as needed
cp frontend/env.example frontend/.env.local # consumed by Next.jsspring.application.name=tutorial
server.port=8080
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
# Example external database configuration (uncomment and adjust as needed)
# spring.datasource.url=jdbc:postgresql://localhost:5432/app
# spring.datasource.username=app_user
# spring.datasource.password=changeMeNEXT_PUBLIC_API_BASE_URL=http://localhost:8080# Terminal 1 - backend
cd backend
./mvnw spring-boot:run
# Terminal 2 - frontend
cd frontend
npm run devAccess the UI at http://localhost:3000; the API listens on http://localhost:8080.
chmod +x run.sh
./run.shThe script launches both services and traps SIGINT to terminate them cleanly.
- Update
NEXT_PUBLIC_API_BASE_URLfor staging/production deployments. - Replace the in-memory
UserServicewith a persistent repository layer before production. - Extend
SecurityConfigwith concrete authentication and authorization rules as the product evolves.
