Project Metadata
Overview of the project context, scope, and tech choices.
Overview
- Role
- Full Stack Developer
- Client
- Employee Cooperative
- Type
- Internal Business Application
- Industry
- Retail & E-Commerce
- Platform
- Web
- Duration
- -
Description
A full-stack e-commerce application with a decoupled architecture, featuring a Next.js frontend and Spring Boot backend, supporting product catalog, shopping cart, and JWT-based authentication.
Key Features
- • User Authentication
- • Decoupled Frontend & Backend
- • Product Catalog & Search
- • Shopping Cart
- • RESTful API
- • Responsive UI
Tech Stack
Built for the company’s employee cooperative, this platform brings product management and online purchasing into a single e-commerce application. It replaces previously manual purchasing workflows with a dedicated digital storefront where users can browse products, manage their cart, and track orders.
The application consists of a Next.js frontend and a Spring Boot backend connected through REST APIs. The implementation covered core e-commerce functionality including product catalogs, shopping carts, user authentication, order management, and communication between the client and server applications.
System Architecture
The platform was built using a decoupled architecture consisting of a Next.js frontend and a Spring Boot backend communicating through REST APIs.
This architecture provided several advantages for a business application:
- Separation of concerns between user interface and business logic
- Independent deployment of frontend and backend services
- Scalability for future growth and additional integrations
- Reusability of backend services for potential future clients, such as mobile applications
The clear API boundary also enabled frontend and backend development to progress independently while maintaining a consistent contract between both systems.
Spring Boot Backend
The backend was built with Spring Boot 3 using a conventional layered architecture:
src/main/java/├── config/ → Application configuration, CORS, beans, and framework setup├── controllers/ → REST API endpoints and request handling├── dto/ → Data Transfer Objects for request and response contracts├── exception/ → Custom exceptions and global exception handlers├── mapper/ → Entity ↔ DTO mapping logic├── models/ → JPA entities and domain models├── payload/ → API request and response payload definitions├── repository/ → Data access layer using Spring Data JPA├── security/ → JWT authentication, authorization, and security configuration├── services/ → Business logic and application services├── uploadmultiple/ → File upload handling and storage utilities└── utils/ → Shared helper functions and utility classesThis separation keeps business logic isolated from transport and persistence layers, making the system easier to maintain and extend.
Authentication is implemented using JWT (JSON Web Token) with Spring Security. Protected endpoints are validated through a security filter before requests reach the application layer, ensuring only authenticated users can access restricted resources.
For data persistence, the application uses PostgreSQL with Spring Data JPA. Entity relationships and queries were designed around common e-commerce workflows such as product browsing, category filtering, product details, and user cart management.
This separation keeps business logic isolated from transport and persistence layers, making the system easier to maintain and extend.
Next.js Frontend
The frontend application was built with Next.js, React, Material UI, and SWR.
Material UI accelerated development by providing a mature component library with consistent styling, accessibility support, and responsive behavior out of the box.
For client-side data fetching and server state management, the application uses SWR. API communication is centralized through a reusable API client, while SWR handles fetching, caching, revalidation, and synchronization of remote data.
const fetcher = <T>(endpoint: string) => apiClient.get<T>(endpoint);
const { data, error, isLoading } = useSWR<Product[]>('/products', fetcher);This approach keeps data-fetching concerns separate from UI components and avoids repeating request logic across different pages. SWR’s caching and revalidation capabilities also help keep frequently accessed data, such as product catalogs, synchronized with the backend.
The frontend includes:
- Buyer dashboard for managing purchases and orders
- Seller dashboard for managing products and sales
- User authentication and session management
- Product catalog browsing
- Product detail pages
- Shopping cart functionality
- Order detail and management
- Responsive layouts for desktop and mobile devices
Integration Challenges
One of the primary technical challenges was managing communication between separate frontend and backend applications.
Since both applications run on different origins during development, proper Cross-Origin Resource Sharing (CORS) configuration was required to allow secure communication between services.
Rather than configuring CORS at individual controller endpoints, the backend uses a centralized Spring Security configuration, providing a single source of control for allowed origins, methods, and headers.
On the frontend, separating API communication from presentation logic through a reusable API client and SWR helped keep remote data handling consistent across different pages and components.
This approach simplified maintenance by reducing duplicated networking logic while providing a predictable pattern for consuming REST APIs.
Key Takeaways
This project provided hands-on experience building and maintaining a business application that spans multiple technology stacks and runtime environments.
Working on both the frontend and backend reinforced the importance of clear API contracts, consistent data models, and maintainable system boundaries. It also highlighted the additional considerations that come with distributed application architectures, where concerns such as authentication, API communication, client-side data management, and deployment must be managed explicitly.
