An Enterprise-Grade, AI-Native Platform for Intelligent Knowledge Curation
Hybrid AI Architecture | Asynchronous Messaging | Military-Grade Security | Full-Stack TypeScript & Java
- Executive Summary
- Why This Project Stands Out
- The Hybrid AI Revolution
- Complete Feature Matrix
- System Architecture
- Technology Stack Deep Dive
- Security Architecture
- Database Design
- API Documentation
- Frontend Architecture
- Testing Strategy
- DevOps & Deployment
- Performance Optimizations
- Code Quality & Patterns
- Installation Guide
- Environment Configuration
- API Reference
- Project Structure
- Contributing
- Roadmap
- License
The Smart Library Management System (SLMS) is not just another CRUD application. It represents the convergence of modern software engineering principles with artificial intelligence, delivering an enterprise-ready platform that manages personal and organizational book collections with unprecedented intelligence.
| Metric | Value |
|---|---|
| Backend Java Files | 88 classes |
| Frontend Components | 39 TSX files |
| REST API Endpoints | 50+ endpoints |
| Database Entities | 5 core entities + 6 enums |
| DTOs | 26 data transfer objects |
| Custom Repositories | 7 with 40+ query methods |
| Services | 22 business logic services |
| Test Classes | 6 comprehensive test suites |
| Lines of Code | 15,000+ |
Unlike typical "AI apps" that are simple ChatGPT wrappers, SLMS implements a dual-engine intelligence system that solves the fundamental latency vs. creativity trade-off in AI applications.
Military-grade security implementation with JWT token blacklisting, Base64 secret obfuscation at runtime, BCrypt password hashing, and role-based access control (RBAC).
Non-blocking newsletter delivery system using Spring's @Async annotation, capable of sending to thousands of subscribers without blocking the UI thread.
End-to-end TypeScript on the frontend with Zod schema validation ensuring runtime type safety matches compile-time guarantees.
Docker Compose orchestration with health checks, multi-stage builds, and Nginx reverse proxy configuration.
Unit tests, integration tests, and security tests using JUnit 5, Mockito, and H2 in-memory database for isolated testing.
Most AI applications suffer from the "dumb or slow" problem: rule-based systems are fast but inflexible, while LLM systems are intelligent but slow and expensive. SLMS solves this with a split-stack approach.
+-----------------------+
| User Query Input |
+-----------+-----------+
|
+-----------v-----------+
| RuleBasedQueryParser |
| (Intent Detection) |
+-----------+-----------+
|
+-----------------+-----------------+
| |
+---------v---------+ +-----------v-----------+
| LOGICAL ENGINE | | CREATIVE ENGINE |
| (Rule-Based) | | (LLM-Based) |
+-------------------+ +-----------------------+
| Latency: < 50ms | | Latency: ~1.5s |
| Source: Database | | Source: GPT-4o |
| Output: Facts | | Output: Insights |
+-------------------+ +-----------------------+
| |
+-----------------+-----------------+
|
+-----------v-----------+
| Combined Response |
| (Fast + Intelligent)|
+-----------------------+
Purpose: Lightning-fast factual queries using direct database aggregations.
Capabilities:
- Total book counts and user statistics
- Genre distribution analysis
- Reading status breakdowns
- Top readers identification
- Library value calculations
- Author popularity rankings
Sample Queries Handled:
- "How many books are in the system?"
- "Who has the most books?"
- "What's the most popular genre?"
- "What's my library worth?"
Performance: < 50ms response time via optimized JPQL queries.
// Example: Custom repository query for genre distribution
@Query("SELECT b.genre, COUNT(b) FROM Book b GROUP BY b.genre ORDER BY COUNT(b) DESC")
List<Object[]> countBooksByGenre();Purpose: Strategic insights and creative recommendations using GPT-4o with context injection.
Capabilities:
- Personalized reading recommendations
- Library gap analysis
- Strategic acquisition suggestions
- Trend identification
- User behavior insights
Context Injection System:
private String buildDatabaseContext(Long userId) {
StringBuilder context = new StringBuilder();
// System-wide stats
context.append(String.format("Total books in system: %d\n", bookRepository.count()));
context.append(String.format("Total users: %d\n", userRepository.count()));
// Genre distribution
bookRepository.countBooksByGenre().forEach(row ->
context.append(String.format("%s=%d, ", row[0], row[1])));
// User-specific context
if (userId != null) {
context.append(String.format("\nCurrent user has %d books.\n",
bookRepository.countByUserId(userId)));
}
return context.toString();
}Sample Output:
"Your library shows a strong preference for Technology books (42%) but lacks Science Fiction classics. Based on similar readers, I recommend exploring Asimov's Foundation series or Philip K. Dick's works to diversify your collection."
The RuleBasedQueryParser class implements pattern matching to route queries to the appropriate engine:
public enum QueryType {
FAVORITE_GENRE, // "What's my favorite genre?"
BOOK_COUNT, // "How many books do I have?"
READING_PROGRESS, // "What am I currently reading?"
TOP_AUTHORS, // "Who are my most-read authors?"
LIBRARY_VALUE, // "What's my library worth?"
RECOMMENDATIONS, // Routed to LLM
UNKNOWN // Fallback to LLM
}| Feature | Implementation | Details |
|---|---|---|
| User Registration | AuthService.register() |
Email validation, BCrypt hashing, verification token generation |
| Email Verification | TokenService + EmailService |
24-hour expiry tokens, resend capability |
| Login System | JWT-based | 24-hour token expiry, stateless sessions |
| Password Reset | Token-based flow | 1-hour expiry, confirmation emails |
| Logout | Token blacklisting | In-memory deny list with hourly cleanup |
| Role-Based Access | ADMIN / USER roles | Method-level security with @PreAuthorize |
| Route Protection | ProtectedRoute.tsx |
Client-side guards before API calls |
| Feature | Implementation | Details |
|---|---|---|
| CRUD Operations | BookController + BookService |
Full create, read, update, delete |
| Personal Libraries | User-scoped queries | Each user has isolated book collection |
| Reading Status Tracking | ReadingStatus enum |
TO_READ, READING, COMPLETED |
| Genre Classification | Genre enum |
10+ genres supported |
| Advanced Metadata | Book entity |
ISBN, page count, publication year, price, description |
| Pagination | PagedResponse<T> |
Configurable page size with total counts |
| Multi-Criteria Search | BookSpecification |
Dynamic query building with JPA Specifications |
| Feature | Implementation | Details |
|---|---|---|
| Full-Text Search | JPQL LIKE queries | Case-insensitive, partial matching |
| Faceted Filtering | SearchService |
Filter by genre, status, price range, year |
| Auto-Suggestions | findDistinctTitlesByUserIdAndQuery |
Real-time search suggestions |
| Price Range Filtering | BookSpecification |
Min/max price constraints |
| Publication Year Filtering | BookSpecification |
Year range constraints |
| Debounced Search | useDebounce hook |
300ms delay to prevent API flooding |
| Feature | Implementation | Details |
|---|---|---|
| System Statistics | AdminService |
Total users, books, active sessions |
| User Management | AdminController |
View, search, delete users |
| User Detail View | UserDetailPage.tsx |
View user's complete book collection |
| Genre Distribution Charts | countBooksByGenre() |
Visual breakdown of all books |
| Top Readers Leaderboard | countBooksPerUser() |
Ranked by book count |
| Most Popular Authors | findTopAuthors() |
Cross-user author rankings |
| AI-Powered Insights | AIAdminInsightsService |
Strategic recommendations |
| System-Wide Search | searchAllBooks() |
Search across all users' books |
| Feature | Implementation | Details |
|---|---|---|
| Newsletter CRUD | NewsletterService |
Draft, edit, delete newsletters |
| Lifecycle Management | NewsletterStatus enum |
DRAFT, SENDING, SENT, FAILED |
| Async Delivery | @Async sendNewsletterAsync() |
Non-blocking bulk email |
| Subscriber Management | NotificationPreferences |
User-controlled subscription |
| Unsubscribe Links | Token-based | One-click unsubscribe in emails |
| Delivery Statistics | recipientCount tracking |
Real-time delivery monitoring |
| Email Templates | EmailService |
HTML templates for all email types |
| Email Type | Trigger | Template Features |
|---|---|---|
| Verification Email | User registration | Clickable verification link, 24h expiry |
| Welcome Email | Email verified | Personalized greeting |
| Password Reset | Forgot password request | Secure reset link, 1h expiry |
| Password Changed | Successful reset | Security confirmation |
| Newsletter | Admin sends | Rich content, unsubscribe link |
| Feature | Implementation | Details |
|---|---|---|
| Natural Language Queries | AIQueryController |
Ask questions in plain English |
| Intent Detection | RuleBasedQueryParser |
Pattern matching for common queries |
| LLM Fallback | OpenAIService |
GPT-4o for complex queries |
| Context Injection | buildDatabaseContext() |
Database stats fed to LLM |
| Personalized Insights | AIUserInsightsService |
User-specific recommendations |
| Collaborative Filtering | findUsersWithSimilarBooks() |
"Users like you also read..." |
| Genre-Based Recommendations | findPopularBooksInGenreNotOwnedByUser() |
Fill gaps in collection |
| Feature | Implementation | Details |
|---|---|---|
| Notification Preferences | NotificationPreferencesController |
Toggle email types |
| Newsletter Subscription | newsletterEnabled flag |
Opt-in/opt-out |
| Weekly Digest | weeklyDigestEnabled flag |
Periodic summaries |
| Unsubscribe Token | UUID-based | Secure one-click unsubscribe |
+------------------------------------------------------------------+
| CLIENT LAYER |
| +------------------------------------------------------------+ |
| | React 19 + TypeScript | |
| | +------------+ +------------+ +------------+ | |
| | | Pages | | Components | | Services | | |
| | | (22 views) | | (17 common)| | (10 APIs) | | |
| | +------------+ +------------+ +------------+ | |
| | | | |
| | +------------------+ | +------------------+ | |
| | | AuthContext | | | React Router | | |
| | | (Global State) | | | (Navigation) | | |
| | +------------------+ | +------------------+ | |
| +------------------------------------------------------------+ |
| | Axios + JWT |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| API GATEWAY |
| +------------------------------------------------------------+ |
| | Spring Security Filter Chain | |
| | +------------------+ +------------------+ | |
| | | CORS Filter | | JWT Auth Filter | | |
| | +------------------+ +------------------+ | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| CONTROLLER LAYER |
| +------------+ +------------+ +------------+ +------------+ |
| | Auth | | Book | | Admin | | Newsletter | |
| | Controller | | Controller | | Controller | | Controller | |
| +------------+ +------------+ +------------+ +------------+ |
| +------------+ +------------+ +------------+ +------------+ |
| | AIQuery | | Search | | Recommend | | Health | |
| | Controller | | Controller | | Controller | | Controller | |
| +------------+ +------------+ +------------+ +------------+ |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| SERVICE LAYER |
| +------------------------------------------------------------+ |
| | +---------------+ +---------------+ +---------------+ | |
| | | AuthService | | BookService | | UserService | | |
| | +---------------+ +---------------+ +---------------+ | |
| | +---------------+ +---------------+ +---------------+ | |
| | | EmailService | | TokenService | | SearchService | | |
| | +---------------+ +---------------+ +---------------+ | |
| | +---------------+ +---------------+ +---------------+ | |
| | | Newsletter | | Notification | | Recommend | | |
| | | Service | | Service | | Service | | |
| | +---------------+ +---------------+ +---------------+ | |
| +------------------------------------------------------------+ |
| | |
| +------------------------------------------------------------+ |
| | AI SERVICE LAYER | |
| | +------------------+ +------------------+ | |
| | | AIAdminInsights | | AIUserInsights | | |
| | | (Rule-Based) | | (LLM-Based) | | |
| | +------------------+ +------------------+ | |
| | | | | |
| | +------------------+ +------------------+ | |
| | | RuleBasedParser | | OpenAIService | | |
| | +------------------+ +------------------+ | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| REPOSITORY LAYER |
| +------------+ +------------+ +------------+ +------------+ |
| | User | | Book | | Newsletter | | Token | |
| | Repository | | Repository | | Repository | | Repository | |
| +------------+ +------------+ +------------+ +------------+ |
| +------------------------------------------------------------+ |
| | JPA Specifications (Dynamic Queries) | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+
|
v
+------------------------------------------------------------------+
| DATA LAYER |
| +------------------------------------------------------------+ |
| | PostgreSQL 16 | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | | users | | books | |newsletters| | tokens | | |
| | +----------+ +----------+ +----------+ +----------+ | |
| | +----------------------------------------------------+ | |
| | | notification_preferences | | |
| | +----------------------------------------------------+ | |
| +------------------------------------------------------------+ |
+------------------------------------------------------------------+
The application follows a strict layered architecture with clear separation of concerns:
+-----------------------------------------------------------------+
| PRESENTATION LAYER |
| Controllers handle HTTP requests and return ResponseEntity |
| - Input validation via @Valid annotations |
| - Exception handling via @ControllerAdvice |
+-----------------------------------------------------------------+
|
v
+-----------------------------------------------------------------+
| BUSINESS LAYER |
| Services contain all business logic |
| - Transaction management via @Transactional |
| - Business rule enforcement |
| - Cross-cutting concerns (logging, security) |
+-----------------------------------------------------------------+
|
v
+-----------------------------------------------------------------+
| PERSISTENCE LAYER |
| Repositories handle data access |
| - JPA/Hibernate for ORM |
| - Custom JPQL queries for complex operations |
| - Specifications for dynamic filtering |
+-----------------------------------------------------------------+
|
v
+-----------------------------------------------------------------+
| DATA LAYER |
| PostgreSQL database with normalized schema |
| - Foreign key constraints |
| - Indexes for performance |
| - Cascade operations |
+-----------------------------------------------------------------+
| Technology | Version | Purpose | Key Features Used |
|---|---|---|---|
| Java | 21 LTS | Core Language | Records, Pattern Matching, Virtual Threads, Text Blocks |
| Spring Boot | 4.0.0 | Application Framework | Auto-configuration, Embedded Tomcat, Actuator |
| Spring Security | 6.x | Security Framework | JWT filters, BCrypt, Method Security |
| Spring Data JPA | 3.x | Data Access | Repositories, Specifications, Pagination |
| Hibernate | 6.x | ORM | Entity mapping, Lazy loading, Caching |
| PostgreSQL | 16 | Database | ACID compliance, JSON support, Full-text search |
| JJWT | 0.12.5 | JWT Library | Token generation, validation, parsing |
| Lombok | Latest | Boilerplate Reduction | @Data, @Builder, @Slf4j |
| Jackson | 2.x | JSON Processing | Serialization, ObjectMapper |
| Spring Mail | 3.x | Email Service | SMTP integration, HTML templates |
| SpringDoc OpenAPI | 3.0.0 | API Documentation | Swagger UI, OpenAPI 3.0 spec |
| Technology | Version | Purpose | Key Features Used |
|---|---|---|---|
| React | 19.2.0 | UI Library | Hooks, Context API, Strict Mode |
| TypeScript | 5.9.3 | Type Safety | Strict mode, Generics, Type guards |
| Vite | 7.2.4 | Build Tool | HMR, ES modules, Optimized builds |
| React Router | 7.10.1 | Navigation | Nested routes, Protected routes, Params |
| Axios | 1.13.2 | HTTP Client | Interceptors, Request/Response transforms |
| React Hook Form | 7.68.0 | Form Management | Validation, Error handling, Performance |
| Zod | 4.2.1 | Schema Validation | Type inference, Runtime validation |
| Tailwind CSS | 3.4.14 | Styling | Utility-first, Responsive design |
| React Hot Toast | 2.6.0 | Notifications | Toast messages, Custom styling |
| clsx | 2.1.1 | Class Names | Conditional classes |
| Technology | Version | Purpose |
|---|---|---|
| Docker | Latest | Containerization |
| Docker Compose | 3.x | Orchestration |
| Nginx | Alpine | Reverse Proxy |
| Maven | 3.9+ | Build Tool |
| Git | 2.x | Version Control |
+-----------------------------------------------------------------+
| TRANSPORT LAYER SECURITY |
| - HTTPS enforcement (production) |
| - CORS configuration for allowed origins |
+-----------------------------------------------------------------+
|
v
+-----------------------------------------------------------------+
| AUTHENTICATION LAYER |
| - JWT token validation |
| - Token expiration checking |
| - Token blacklist verification |
+-----------------------------------------------------------------+
|
v
+-----------------------------------------------------------------+
| AUTHORIZATION LAYER |
| - Role-based access control (RBAC) |
| - Method-level security (@PreAuthorize) |
| - Resource ownership validation |
+-----------------------------------------------------------------+
|
v
+-----------------------------------------------------------------+
| DATA LAYER SECURITY |
| - User-scoped queries |
| - SQL injection prevention (JPA) |
| - Input validation (@Valid) |
+-----------------------------------------------------------------+
+----------+ +----------+ +----------+
| Client | | Server | | Database |
+----+-----+ +----+-----+ +----+-----+
| | |
| POST /api/auth/login |
| {email, password} | |
|-------------------->| |
| | |
| | Validate user |
| |-------------------->|
| |<--------------------|
| | |
| | Generate JWT |
| | (24h expiry) |
| | |
| {token, user} | |
|<--------------------| |
| | |
| GET /api/books | |
| Authorization: | |
| Bearer <token> | |
|-------------------->| |
| | |
| | Validate JWT |
| | Check blacklist |
| | Extract user ID |
| | |
| | Fetch user books |
| |-------------------->|
| |<--------------------|
| | |
| {books: [...]} | |
|<--------------------| |
| | |
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// Disable CSRF (stateless REST API)
.csrf(AbstractHttpConfigurer::disable)
// Enable CORS with specific origins
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
// Stateless session management
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
// Authorization rules
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/health").permitAll()
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
// JWT filter before username/password filter
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}Unlike typical applications that store secrets in plain text configuration files, SLMS implements runtime secret decoding:
@Configuration
public class SecretDecoderConfig {
@Value("${app.security.encoded-openai:}")
private String encodedOpenAI;
@Value("${app.security.encoded-gmail:}")
private String encodedGmail;
@PostConstruct
public void decodeSecrets() {
// Decode Base64 secrets at runtime
if (!encodedOpenAI.isBlank()) {
String decoded = new String(Base64.getDecoder().decode(encodedOpenAI));
System.setProperty("openai.api.key", decoded);
}
if (!encodedGmail.isBlank()) {
String decoded = new String(Base64.getDecoder().decode(encodedGmail));
System.setProperty("spring.mail.password", decoded);
}
}
}Security Benefits:
- Secrets are not stored in plain text in memory
- Configuration files don't contain readable credentials
- Runtime injection prevents static analysis exposure
Prevents JWT replay attacks by maintaining an in-memory deny list:
@Service
public class TokenBlacklistService {
private final ConcurrentHashMap<String, Long> blacklist = new ConcurrentHashMap<>();
public void blacklistToken(String token) {
// Store token with its expiration time
Claims claims = jwtService.extractAllClaims(token);
blacklist.put(token, claims.getExpiration().getTime());
}
public boolean isBlacklisted(String token) {
return blacklist.containsKey(token);
}
@Scheduled(fixedRate = 3600000) // Hourly cleanup
public void cleanupExpiredTokens() {
long now = System.currentTimeMillis();
blacklist.entrySet().removeIf(entry -> entry.getValue() < now);
}
}- Hashing Algorithm: BCrypt with default strength (10 rounds)
- Salt: Automatically generated per password
- Verification: Timing-safe comparison
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}- Token Type: UUID-based random tokens
- Expiration: 24 hours for verification, 1 hour for password reset
- One-Time Use: Tokens deleted after successful verification
- Rate Limiting: Configurable resend cooldown
+-----------------------------------------------------------------+
| USERS |
+-----------------------------------------------------------------+
| id (PK) | BIGINT | Auto-increment |
| email | VARCHAR(255) | Unique, Not Null |
| password | VARCHAR(255) | BCrypt hashed |
| name | VARCHAR(255) | Not Null |
| role | VARCHAR(20) | ADMIN / USER |
| email_verified | BOOLEAN | Default: false |
| created_at | TIMESTAMP | Auto-set on creation |
| updated_at | TIMESTAMP | Auto-updated |
+-----------------------------------------------------------------+
|
+---------------+---------------+
| | |
v v v
+---------------------+ +-------------------+ +---------------------+
| BOOKS | | TOKENS | | NOTIFICATION_PREFS |
+---------------------+ +-------------------+ +---------------------+
| id (PK) | | id (PK) | | id (PK) |
| title | | token | | user_id (FK) |
| author | | token_type | | newsletter_enabled |
| genre | | user_id (FK) | | weekly_digest |
| status | | expiry_date | | unsubscribe_token |
| price | | created_at | | created_at |
| description | +-------------------+ | updated_at |
| isbn | +---------------------+
| page_count |
| publication_year |
| user_id (FK) |
| created_at |
| updated_at |
+---------------------+
+-----------------------------------------------------------------+
| NEWSLETTERS |
+-----------------------------------------------------------------+
| id (PK) | BIGINT | Auto-increment |
| subject | VARCHAR(255) | Not Null |
| content | TEXT | Rich HTML content |
| status | VARCHAR(20) | DRAFT/SENDING/SENT/FAILED |
| created_by_id | BIGINT (FK) | Admin who created |
| recipient_count | INTEGER | Delivery count |
| sent_at | TIMESTAMP | When newsletter was sent |
| created_at | TIMESTAMP | Auto-set |
| updated_at | TIMESTAMP | Auto-updated |
+-----------------------------------------------------------------+
// Reading status tracking
public enum ReadingStatus {
TO_READ, // Book is in queue
READING, // Currently being read
COMPLETED // Finished reading
}
// Book genres
public enum Genre {
TECHNOLOGY,
FICTION,
NON_FICTION,
MYSTERY,
SCIENCE_FICTION,
FANTASY,
BIOGRAPHY,
HISTORY,
SELF_HELP,
ROMANCE,
THRILLER,
HORROR,
OTHER
}
// User roles
public enum Role {
ADMIN,
USER
}
// Newsletter lifecycle
public enum NewsletterStatus {
DRAFT,
SENDING,
SENT,
FAILED
}
// Token types
public enum TokenType {
EMAIL_VERIFICATION,
PASSWORD_RESET
}The BookRepository contains 40+ custom query methods including:
@Repository
public interface BookRepository extends JpaRepository<Book, Long>,
JpaSpecificationExecutor<Book> {
// User-scoped queries
Page<Book> findByUserId(Long userId, Pageable pageable);
Page<Book> findByUserIdAndGenre(Long userId, Genre genre, Pageable pageable);
Page<Book> findByUserIdAndStatus(Long userId, ReadingStatus status, Pageable pageable);
// Analytics queries
@Query("SELECT b.genre, COUNT(b) FROM Book b GROUP BY b.genre")
List<Object[]> countBooksByGenre();
@Query("SELECT b.user.id, b.user.name, COUNT(b) FROM Book b " +
"GROUP BY b.user.id, b.user.name ORDER BY COUNT(b) DESC")
List<Object[]> countBooksPerUser();
// Recommendation queries
@Query("SELECT DISTINCT b2.user.id FROM Book b1 " +
"JOIN Book b2 ON b1.title = b2.title " +
"WHERE b1.user.id = :userId AND b2.user.id != :userId")
List<Long> findUsersWithSimilarBooks(@Param("userId") Long userId);
// Search queries
@Query("SELECT DISTINCT b.author FROM Book b WHERE b.user.id = :userId " +
"AND LOWER(b.author) LIKE LOWER(CONCAT('%', :query, '%'))")
List<String> findDistinctAuthorsByUserIdAndQuery(Long userId, String query, Pageable pageable);
}The system includes auto-generated API documentation via SpringDoc OpenAPI:
Access: http://localhost:8081/swagger-ui.html
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/auth/register |
Register new user | No |
POST |
/api/auth/login |
Authenticate user | No |
POST |
/api/auth/logout |
Invalidate token | Yes |
GET |
/api/auth/verify-email |
Verify email token | No |
POST |
/api/auth/resend-verification |
Resend verification email | No |
POST |
/api/auth/forgot-password |
Request password reset | No |
POST |
/api/auth/reset-password |
Reset password | No |
GET |
/api/auth/me |
Get current user | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/books |
Get user's books (paginated) | Yes |
GET |
/api/books/{id} |
Get specific book | Yes |
POST |
/api/books |
Create new book | Yes |
PUT |
/api/books/{id} |
Update book | Yes |
DELETE |
/api/books/{id} |
Delete book | Yes |
GET |
/api/books/count |
Get book count | Yes |
GET |
/api/books/stats |
Get reading statistics | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/search |
Advanced search | Yes |
GET |
/api/search/suggestions |
Auto-complete suggestions | Yes |
GET |
/api/search/filters |
Get available filter options | Yes |
GET |
/api/search/facets |
Get faceted counts | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/api/ai/query |
Natural language query | Yes |
GET |
/api/ai/insights |
Get AI-generated insights | Yes |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/admin/stats |
System statistics | Admin |
GET |
/api/admin/users |
List all users | Admin |
GET |
/api/admin/users/{id} |
Get user details | Admin |
DELETE |
/api/admin/users/{id} |
Delete user | Admin |
GET |
/api/admin/books |
Search all books | Admin |
POST |
/api/admin/books |
Add book to shared library | Admin |
GET |
/api/admin/insights |
Admin analytics | Admin |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/admin/newsletters |
List newsletters | Admin |
GET |
/api/admin/newsletters/{id} |
Get newsletter | Admin |
POST |
/api/admin/newsletters |
Create newsletter | Admin |
PUT |
/api/admin/newsletters/{id} |
Update newsletter | Admin |
DELETE |
/api/admin/newsletters/{id} |
Delete draft | Admin |
POST |
/api/admin/newsletters/{id}/send |
Send newsletter | Admin |
GET |
/api/admin/newsletters/stats |
Newsletter statistics | Admin |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/api/recommendations |
Get personalized recommendations | Yes |
GET |
/api/recommendations/similar |
Books from similar users | Yes |
GET |
/api/recommendations/genre/{genre} |
Genre-based recommendations | Yes |
Register User:
// POST /api/auth/register
// Request:
{
"email": "user@example.com",
"password": "SecurePass123!",
"name": "John Doe"
}
// Response (201 Created):
{
"message": "Registration successful. Please check your email to verify your account.",
"userId": 1
}Create Book:
// POST /api/books
// Request:
{
"title": "Clean Code",
"author": "Robert C. Martin",
"genre": "TECHNOLOGY",
"status": "READING",
"isbn": "978-0132350884",
"pageCount": 464,
"publicationYear": 2008,
"price": 49.99,
"description": "A Handbook of Agile Software Craftsmanship"
}
// Response (201 Created):
{
"id": 1,
"title": "Clean Code",
"author": "Robert C. Martin",
"genre": "TECHNOLOGY",
"status": "READING",
"isbn": "978-0132350884",
"pageCount": 464,
"publicationYear": 2008,
"price": 49.99,
"description": "A Handbook of Agile Software Craftsmanship",
"createdAt": "2024-01-15T10:30:00",
"updatedAt": "2024-01-15T10:30:00"
}AI Query:
// POST /api/ai/query
// Request:
{
"query": "What's my favorite genre and why?"
}
// Response:
{
"queryType": "FAVORITE_GENRE",
"answer": "Based on your library, Technology is your favorite genre with 15 books (42% of your collection). You seem particularly interested in software engineering and clean code practices, with multiple books by Robert C. Martin and Martin Fowler.",
"recognizedQuery": true,
"confidence": 0.95,
"processingMethod": "RULE_BASED"
}App.tsx
├── AuthContext.tsx (Global State Provider)
│
├── Routes
│ ├── Public Routes
│ │ ├── LoginPage.tsx
│ │ ├── RegisterPage.tsx
│ │ ├── ForgotPasswordPage.tsx
│ │ ├── ResetPasswordPage.tsx
│ │ └── VerifyEmailPage.tsx
│ │
│ ├── Protected Routes (ProtectedRoute.tsx wrapper)
│ │ ├── Layout.tsx
│ │ │ ├── Navbar.tsx
│ │ │ └── Sidebar.tsx
│ │ │
│ │ ├── User Routes
│ │ │ ├── DashboardPage.tsx
│ │ │ ├── BooksPage.tsx
│ │ │ ├── AddBookPage.tsx
│ │ │ ├── EditBookPage.tsx
│ │ │ ├── BookDetailPage.tsx
│ │ │ ├── SearchPage.tsx
│ │ │ ├── LibraryPage.tsx
│ │ │ └── SettingsPage.tsx
│ │ │
│ │ └── Admin Routes (Admin check)
│ │ ├── AdminDashboardPage.tsx
│ │ ├── AdminBooksPage.tsx
│ │ ├── AdminAddBookPage.tsx
│ │ ├── AdminSearchPage.tsx
│ │ ├── UserListPage.tsx
│ │ ├── UserDetailPage.tsx
│ │ └── NewsletterPage.tsx
│ │
│ └── Notification Routes
│ ├── UnsubscribePage.tsx
│ └── UnsubscribeNewsletterPage.tsx
│
└── Common Components
├── Button.tsx
├── Input.tsx
├── Card.tsx
├── Modal.tsx
├── Badge.tsx
├── Spinner.tsx
├── Pagination.tsx
├── EmptyState.tsx
├── BookCard.tsx
└── BookForm.tsx
Authentication Context:
interface AuthContextType {
user: User | null;
token: string | null;
isAuthenticated: boolean;
isLoading: boolean;
login: (email: string, password: string) => Promise<void>;
logout: () => void;
register: (data: RegisterData) => Promise<void>;
}
export const AuthContext = createContext<AuthContextType | undefined>(undefined);
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [user, setUser] = useState<User | null>(null);
const [token, setToken] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true);
// Persist auth state to localStorage
useEffect(() => {
const storedToken = localStorage.getItem(TOKEN_STORAGE_KEY);
const storedUser = localStorage.getItem(USER_STORAGE_KEY);
if (storedToken && storedUser) {
setToken(storedToken);
setUser(JSON.parse(storedUser));
}
setIsLoading(false);
}, []);
// ... login, logout, register implementations
return (
<AuthContext.Provider value={{ user, token, isAuthenticated, isLoading, login, logout, register }}>
{children}
</AuthContext.Provider>
);
};useAuth Hook:
export const useAuth = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};useDebounce Hook:
export function useDebounce<T>(value: T, delay: number): T {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}Axios Instance with Interceptors:
const api = axios.create({
baseURL: API_BASE_URL,
headers: {
'Content-Type': 'application/json',
},
});
// Request interceptor - inject JWT
api.interceptors.request.use((config) => {
const token = localStorage.getItem(TOKEN_STORAGE_KEY);
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
});
// Response interceptor - handle 401
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
localStorage.removeItem(TOKEN_STORAGE_KEY);
localStorage.removeItem(USER_STORAGE_KEY);
window.location.href = '/login';
}
return Promise.reject(error);
}
);const bookSchema = z.object({
title: z.string().min(1, 'Title is required').max(255),
author: z.string().min(1, 'Author is required').max(255),
genre: z.nativeEnum(Genre),
status: z.nativeEnum(ReadingStatus),
isbn: z.string().regex(/^(?:\d{10}|\d{13})$/, 'ISBN must be 10 or 13 digits').optional(),
pageCount: z.number().int().positive().optional(),
publicationYear: z.number().int().min(1000).max(2100).optional(),
price: z.number().positive().optional(),
description: z.string().max(2000).optional(),
});
type BookFormData = z.infer<typeof bookSchema>;// types/index.ts
export interface User {
id: number;
email: string;
name: string;
role: 'ADMIN' | 'USER';
emailVerified: boolean;
createdAt: string;
}
export interface Book {
id: number;
title: string;
author: string;
genre: Genre;
status: ReadingStatus;
isbn?: string;
pageCount?: number;
publicationYear?: number;
price?: number;
description?: string;
createdAt: string;
updatedAt: string;
}
export interface PagedResponse<T> {
content: T[];
totalElements: number;
totalPages: number;
size: number;
number: number;
first: boolean;
last: boolean;
}
export enum Genre {
TECHNOLOGY = 'TECHNOLOGY',
FICTION = 'FICTION',
// ... other genres
}
export enum ReadingStatus {
TO_READ = 'TO_READ',
READING = 'READING',
COMPLETED = 'COMPLETED',
}src/test/java/com/library/library_management/
├── LibraryManagementApplicationTests.java # Context loading test
├── controller/
│ ├── AuthControllerIntegrationTest.java # Auth endpoint integration tests
│ └── BookControllerIntegrationTest.java # Book endpoint integration tests
├── service/
│ ├── AuthServiceTest.java # Auth service unit tests
│ └── BookServiceTest.java # Book service unit tests
└── security/
└── JwtServiceTest.java # JWT generation/validation tests
@ExtendWith(MockitoExtension.class)
class BookServiceTest {
@Mock
private BookRepository bookRepository;
@Mock
private UserRepository userRepository;
@InjectMocks
private BookService bookService;
@Nested
@DisplayName("Create Book Tests")
class CreateBookTests {
@Test
@DisplayName("Should create book successfully")
void shouldCreateBook() {
// Arrange
Long userId = 1L;
BookRequest request = BookRequest.builder()
.title("Test Book")
.author("Test Author")
.genre(Genre.TECHNOLOGY)
.status(ReadingStatus.TO_READ)
.build();
User user = new User();
user.setId(userId);
when(userRepository.findById(userId)).thenReturn(Optional.of(user));
when(bookRepository.save(any(Book.class))).thenAnswer(invocation -> {
Book book = invocation.getArgument(0);
book.setId(1L);
return book;
});
// Act
BookResponse response = bookService.createBook(request, userId);
// Assert
assertNotNull(response);
assertEquals("Test Book", response.getTitle());
verify(bookRepository, times(1)).save(any(Book.class));
}
@Test
@DisplayName("Should throw exception when user not found")
void shouldThrowWhenUserNotFound() {
// Arrange
Long userId = 999L;
BookRequest request = new BookRequest();
when(userRepository.findById(userId)).thenReturn(Optional.empty());
// Act & Assert
assertThrows(ResourceNotFoundException.class,
() -> bookService.createBook(request, userId));
}
}
@Nested
@DisplayName("Filter Books Tests")
class FilterBooksTests {
@Test
@DisplayName("Should filter by genre")
void shouldFilterByGenre() {
// ... test implementation
}
@Test
@DisplayName("Should filter by status")
void shouldFilterByStatus() {
// ... test implementation
}
}
}@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@ActiveProfiles("test")
class AuthControllerIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private UserRepository userRepository;
@BeforeEach
void setUp() {
userRepository.deleteAll();
}
@Test
@DisplayName("Should register user successfully")
void shouldRegisterUser() throws Exception {
RegisterRequest request = new RegisterRequest();
request.setEmail("test@example.com");
request.setPassword("Password123!");
request.setName("Test User");
mockMvc.perform(post("/api/auth/register")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.message").exists());
}
@Test
@DisplayName("Should reject duplicate email")
void shouldRejectDuplicateEmail() throws Exception {
// Create first user
// ...
// Try to register same email
mockMvc.perform(post("/api/auth/register")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)))
.andExpect(status().isBadRequest());
}
}spring:
datasource:
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
driver-class-name: org.h2.Driver
username: sa
password:
jpa:
hibernate:
ddl-auto: create-drop
database-platform: org.hibernate.dialect.H2Dialect
jwt:
secret: testSecretKeyThatIsAtLeast256BitsLongForTesting123456789!
expiration: 86400000
app:
base-url: http://localhost:8081
frontend-url: http://localhost:5173Backend Dockerfile:
# Multi-stage build for optimized image size
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:resolve
COPY src ./src
RUN ./mvnw package -DskipTests
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
# Run as non-root user for security
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8081
ENTRYPOINT ["java", "-jar", "app.jar"]Frontend Dockerfile:
# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]Docker Compose:
services:
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: library_db
POSTGRES_USER: library_user
POSTGRES_PASSWORD: 123456
volumes:
- db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U library_user -d library_db"]
interval: 10s
timeout: 5s
retries: 5
backend:
build:
context: .
dockerfile: Dockerfile
image: library-management-backend
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/library_db
SPRING_DATASOURCE_USERNAME: library_user
SPRING_DATASOURCE_PASSWORD: 123456
APP_BASE_URL: http://localhost:8081
APP_FRONTEND_URL: http://localhost:8080
ports:
- "8081:8081"
depends_on:
db:
condition: service_healthy
frontend:
build:
context: ./front-end
dockerfile: Dockerfile
image: library-management-frontend
ports:
- "8080:80"
depends_on:
- backend
volumes:
db_data:# Build and start all services
docker-compose up --build
# Start in detached mode
docker-compose up -d
# View logs
docker-compose logs -f
# Stop all services
docker-compose down
# Stop and remove volumes
docker-compose down -vserver {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# React Router support
location / {
try_files $uri $uri/ /index.html;
}
# API proxy
location /api {
proxy_pass http://backend:8081;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript;
}- Lazy Loading: Entities use
FetchType.LAZYto prevent N+1 queries - Pagination: All list endpoints return paginated results
- Query Optimization: Custom JPQL queries for aggregations
- Connection Pooling: HikariCP (Spring Boot default)
- Async Processing: Newsletter sending doesn't block requests
- Code Splitting: Vite automatic chunk splitting
- Debounced Search: 300ms delay prevents excessive API calls
- Memoization:
useMemofor expensive computations - Lazy Loading: React Router lazy loading (ready for implementation)
- Image Optimization: Next-gen formats support
- Indexes: On frequently queried columns (user_id, genre, status)
- Foreign Keys: Proper relationships with cascade operations
- Connection Pooling: Configured via HikariCP
- Query Caching: Hibernate second-level cache ready
| Pattern | Implementation | Location |
|---|---|---|
| Repository Pattern | Data access abstraction | *Repository.java |
| Service Layer Pattern | Business logic isolation | *Service.java |
| DTO Pattern | Data transfer objects | dto/request/*, dto/response/* |
| Builder Pattern | Object construction | Lombok @Builder |
| Strategy Pattern | AI service selection | LLMService interface |
| Factory Pattern | Response construction | ResponseEntity builders |
| Specification Pattern | Dynamic queries | BookSpecification.java |
| Interceptor Pattern | Request/response processing | JWT filter, Axios interceptors |
| Context Pattern | Global state | AuthContext.tsx |
| Observer Pattern | Event handling | React state updates |
Package Structure (Backend):
com.library.library_management/
├── config/ # Configuration classes
├── controller/ # REST controllers
├── dto/
│ ├── request/ # Incoming DTOs
│ └── response/ # Outgoing DTOs
├── entity/
│ └── enums/ # Enum definitions
├── exception/ # Custom exceptions
├── repository/
│ └── specification/# JPA Specifications
├── security/ # JWT and auth
└── service/
└── ai/ # AI services
Directory Structure (Frontend):
src/
├── components/
│ ├── common/ # Reusable UI components
│ ├── books/ # Book-specific components
│ └── layout/ # Layout components
├── context/ # React contexts
├── hooks/ # Custom hooks
├── pages/
│ ├── admin/ # Admin pages
│ ├── auth/ # Authentication pages
│ ├── books/ # Book management pages
│ ├── dashboard/ # User dashboard
│ ├── library/ # Shared library
│ ├── notifications/# Notification pages
│ ├── search/ # Search page
│ └── settings/ # User settings
├── services/ # API services
├── types/ # TypeScript types
└── utils/ # Utility functions
- Java 21 JDK (Eclipse Temurin recommended)
- Node.js 20+ (LTS version)
- PostgreSQL 16
- Maven 3.9+ (or use included wrapper)
- Docker & Docker Compose (for containerized deployment)
-- Connect to PostgreSQL
psql -U postgres
-- Create database and user
CREATE DATABASE library_db;
CREATE USER library_user WITH PASSWORD '123456';
GRANT ALL PRIVILEGES ON DATABASE library_db TO library_user;
\c library_db
GRANT ALL ON SCHEMA public TO library_user;# Clone repository
git clone https://github.com/yourusername/library-management.git
cd library-management
# Configure secrets (see Environment Configuration section)
# Edit src/main/resources/application.yml
# Build and run
./mvnw spring-boot:runThe backend will start on http://localhost:8081.
# Navigate to frontend
cd front-end
# Install dependencies
npm install
# Start development server
npm run devThe frontend will start on http://localhost:5173.
# Clone repository
git clone https://github.com/yourusername/library-management.git
cd library-management
# Start all services
docker-compose up --buildServices will be available at:
- Frontend:
http://localhost:8080 - Backend:
http://localhost:8081 - Swagger UI:
http://localhost:8081/swagger-ui.html
server:
port: 8081
spring:
profiles:
active: dev
datasource:
url: jdbc:postgresql://localhost:5432/library_db
username: library_user
password: 123456
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
mail:
host: smtp.gmail.com
port: 587
username: your-email@gmail.com
properties:
mail:
smtp:
auth: true
starttls:
enable: true
jwt:
secret: myVeryLongAndSecureSecretKeyThatIsAtLeast256BitsLongForHS256Algorithm2024!
expiration: 86400000 # 24 hours in milliseconds
openai:
api:
url: https://api.openai.com/v1/chat/completions
model: gpt-4o-mini
app:
name: Library Management System
base-url: http://localhost:8081
frontend-url: http://localhost:5173
email:
verification-token-expiry: 86400000 # 24 hours
password-reset-token-expiry: 3600000 # 1 hour
security:
encoded-openai: <base64-encoded-openai-key>
encoded-gmail: <base64-encoded-gmail-password># Encode OpenAI API key
echo -n "sk-your-openai-key" | base64
# Encode Gmail App Password
echo -n "your-gmail-app-password" | base64src/utils/constants.ts:
export const API_BASE_URL = 'http://localhost:8081';
export const TOKEN_STORAGE_KEY = 'library_token';
export const USER_STORAGE_KEY = 'library_user';library-management/
├── docker-compose.yml # Docker orchestration
├── Dockerfile # Backend Docker config
├── pom.xml # Maven configuration
├── mvnw # Maven wrapper
├── README.md # This file
│
├── src/
│ ├── main/
│ │ ├── java/com/library/library_management/
│ │ │ ├── LibraryManagementApplication.java
│ │ │ ├── config/
│ │ │ │ ├── DataLoader.java
│ │ │ │ ├── SecretDecoderConfig.java
│ │ │ │ └── SecurityConfig.java
│ │ │ ├── controller/
│ │ │ │ ├── AdminController.java
│ │ │ │ ├── AIQueryController.java
│ │ │ │ ├── AuthController.java
│ │ │ │ ├── BookController.java
│ │ │ │ ├── HealthController.java
│ │ │ │ ├── LibraryController.java
│ │ │ │ ├── NewsletterController.java
│ │ │ │ ├── NotificationController.java
│ │ │ │ ├── RecommendationController.java
│ │ │ │ └── SearchController.java
│ │ │ ├── dto/
│ │ │ │ ├── request/ (10 DTOs)
│ │ │ │ └── response/ (16 DTOs)
│ │ │ ├── entity/
│ │ │ │ ├── Book.java
│ │ │ │ ├── Newsletter.java
│ │ │ │ ├── NotificationPreferences.java
│ │ │ │ ├── User.java
│ │ │ │ ├── VerificationToken.java
│ │ │ │ └── enums/ (6 enums)
│ │ │ ├── exception/
│ │ │ │ ├── GlobalExceptionHandler.java
│ │ │ │ ├── ResourceNotFoundException.java
│ │ │ │ └── UnauthorizedException.java
│ │ │ ├── repository/
│ │ │ │ ├── BookRepository.java (40+ queries)
│ │ │ │ ├── GlobalBookRepository.java
│ │ │ │ ├── NewsletterRepository.java
│ │ │ │ ├── NotificationPreferencesRepository.java
│ │ │ │ ├── UserRepository.java
│ │ │ │ ├── VerificationTokenRepository.java
│ │ │ │ └── specification/
│ │ │ │ └── BookSpecification.java
│ │ │ ├── security/
│ │ │ │ ├── CustomUserDetails.java
│ │ │ │ ├── CustomUserDetailsService.java
│ │ │ │ ├── JwtAuthenticationFilter.java
│ │ │ │ └── JwtService.java
│ │ │ └── service/
│ │ │ ├── AdminService.java
│ │ │ ├── AIAdminInsightsService.java
│ │ │ ├── AIRecommendationService.java
│ │ │ ├── AIUserInsightsService.java
│ │ │ ├── AuthService.java
│ │ │ ├── BookEventService.java
│ │ │ ├── BookService.java
│ │ │ ├── EmailService.java
│ │ │ ├── GlobalLibraryService.java
│ │ │ ├── NewsletterService.java
│ │ │ ├── NotificationService.java
│ │ │ ├── RecommendationService.java
│ │ │ ├── SearchService.java
│ │ │ ├── TokenBlacklistService.java
│ │ │ ├── TokenService.java
│ │ │ ├── UserInsightsService.java
│ │ │ ├── UserService.java
│ │ │ └── ai/
│ │ │ ├── AIQueryService.java
│ │ │ ├── FallbackLLMService.java
│ │ │ ├── LLMService.java
│ │ │ ├── OpenAIService.java
│ │ │ ├── QueryIntent.java
│ │ │ └── RuleBasedQueryParser.java
│ │ └── resources/
│ │ └── application.yml
│ │
│ └── test/
│ ├── java/com/library/library_management/
│ │ ├── LibraryManagementApplicationTests.java
│ │ ├── controller/ (2 integration tests)
│ │ ├── security/ (1 test)
│ │ └── service/ (2 unit tests)
│ └── resources/
│ └── application-test.yml
│
└── front-end/
├── Dockerfile
├── nginx.conf
├── package.json
├── vite.config.ts
├── tailwind.config.js
├── tsconfig.json
└── src/
├── App.tsx
├── main.tsx
├── index.css
├── components/
│ ├── books/ (2 components)
│ ├── common/ (8 components)
│ └── layout/ (4 components)
├── context/
│ └── AuthContext.tsx
├── hooks/
│ ├── useAuth.ts
│ └── useDebounce.ts
├── pages/
│ ├── admin/ (7 pages)
│ ├── auth/ (5 pages)
│ ├── books/ (4 pages)
│ ├── dashboard/ (1 page)
│ ├── library/ (1 page)
│ ├── notifications/ (2 pages)
│ ├── search/ (1 page)
│ └── settings/ (1 page)
├── services/ (10 API services)
├── types/
│ └── index.ts
└── utils/
├── constants.ts
└── helpers.ts
We welcome contributions! Please follow these guidelines:
- Java: Follow Google Java Style Guide
- TypeScript: ESLint configuration provided
- Commits: Use conventional commit messages
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'feat: add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
type(scope): subject
body
footer
Types: feat, fix, docs, style, refactor, test, chore
- WebSocket integration for real-time notifications
- Redis-based token blacklist for horizontal scaling
- Reading progress tracking (page-by-page)
- Social features (book clubs, reviews)
- Mobile-responsive PWA
- Offline support with service workers
- Book cover image uploads
- Goodreads API integration
- Machine learning-based recommendations
- Natural language search
- Multi-language support (i18n)
- Enterprise SSO integration
This project is licensed under the MIT License - see the LICENSE file for details.