Note: The full source code for this system is closed-source as it belongs to the Valenzuela City Academic Center of Excellence (ValACE). This repository serves as a technical showcase of the system architecture and stack I engineered as a Full-Stack Web Developer Intern.
A comprehensive Online Public Access Catalog (OPAC) system for managing library resources, integrating external APIs, and providing advanced book search capabilities. Built with Laravel backend and React frontend.
- Overview
- Features
- Architecture
- Backend Documentation
- Frontend Documentation
- API Endpoints
- Capabilities
- Deployment
ValACE New OPAC is a modern library management system that enables:
- Resource Management: Create and manage API resources and redirect links to external library systems
- Book Search: Advanced search functionality across multiple integrated resources
- Featured Books: Curate and showcase featured book collections
- API Integration: Connect to external academic databases (EBSCOhost, JSTOR, ProQuest, etc.)
- Sync Management: Granular per-endpoint synchronization with external APIs
- Admin Dashboard: Comprehensive administrative interface for resource management
- π Multi-resource Book Search - Search across internal and external book databases
- π API Resource Integration - Connect to external library APIs with authentication
- π Automated Sync - Scheduled synchronization of external resources
- β Featured Books - Curate and display featured book collections
- π Dashboard Analytics - Monitor system statistics and resource status
- π Activity Logging - Comprehensive logging system for debugging and monitoring
- π Admin Authentication - Secure admin access with token-based auth
- Per-Endpoint Sync Control - Granular synchronization at endpoint level
- Real-time Status Updates - Live sync status monitoring with adaptive polling
- Rate Limiting - Built-in rate limiting for external API calls
- Chunked Processing - Efficient data processing in configurable chunks
- Retry Logic - Automatic retry with exponential backoff
- Search Highlighting - Full-text search with Meilisearch integration
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Frontend (React) β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Pages: Search, Admin Dashboard, Resources, Logs β β
β β Components: UI, Layout, Page-specific β β
β β State: React Query, Context API β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββ
β REST API (JSON)
ββββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββ
β Backend (Laravel) β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Controllers: Resource, Book, Auth, Sync, Log β β
β β Services: Fetch, Store, Update, Search, Sync β β
β β Jobs: Sync, Process, Update (Queue-based) β β
β β Models: Resource, ApiResource, ApiEndpoint, Book β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββΌβββββββββββββ
β β β
βββββββββΌβββββββ ββββΌββββββββ βββΌβββββββββββ
β MySQL DB β β Queue β β Meilisearchβ
β Resources β β Worker β β Search β
β Books β β Jobs β β Index β
ββββββββββββββββ ββββββββββββ ββββββββββββββ
Backend:
- Laravel 10.x (PHP 8.1+)
- MySQL 8.0+
- Meilisearch (Full-text search)
- Queue Workers (Background jobs)
- Composer (Dependency management)
Frontend:
- React 18.x
- Vite (Build tool)
- TailwindCSS (Styling)
- React Query (Data fetching)
- React Router (Routing)
- Axios (HTTP client)
backend/
βββ app/
β βββ Console/ # Artisan commands
β β βββ Commands/ # Custom commands (SyncApiEndpointsCommand)
β βββ Exceptions/ # Exception handlers
β βββ Http/
β β βββ Controllers/ # API controllers
β β βββ Middleware/ # Custom middleware (BasicAuthMiddleware)
β β βββ Resources/ # API resources (transformers)
β βββ Jobs/ # Queue jobs
β β βββ SyncApiEndpointJob.php
β β βββ ProcessExternalResourceChunk.php
β β βββ FetchAndDispatchExternalResource.php
β βββ Logging/ # Custom logging
β β βββ CustomLogger.php
β βββ Models/ # Eloquent models
β β βββ Resource.php
β β βββ ApiResource.php
β β βββ ApiEndpoint.php
β β βββ CacheBook.php
β β βββ FeaturedBook.php
β βββ Services/ # Business logic services
β βββ ResourceDataFetchService.php
β βββ ResourceDataStoreService.php
β βββ ResourceDataUpdateService.php
β βββ ResourceDataDestroyService.php
β βββ BookSearchService.php
β βββ BookFetchService.php
β βββ FeaturedBookService.php
β βββ ExternalResourceFetchService.php
βββ config/ # Configuration files
βββ database/
β βββ migrations/ # Database migrations
β βββ seeders/ # Database seeders
βββ routes/
β βββ api.php # API route definitions
βββ storage/
β βββ logs/ # Application logs
βββ tests/ # PHPUnit tests
Handles fetching and filtering of resources:
fetchAllResources()- Retrieve resources with filtering, sorting, paginationfetchResourceById()- Get single resource with relationshipsfetchActiveResources()- Get only active resources- Supports filtering by type (API/REDIRECT), status (ACTIVE/INACTIVE)
Creates new resources:
storeResource()- Create resource with validation- Handles both API and REDIRECT resource types
- Creates associated ApiResource, ApiEndpoints, and RedirectLink records
Updates existing resources:
updateResource()- Full resource updateupdateStatus()- Update resource status onlyupdateApiConfig()- Update API configurationupdateEndpoints()- Update API endpointsupdateRedirect()- Update redirect link
Manages resource deletion:
deleteResource()- Soft delete resourcedestroyMultipleResources()- Batch deletesoftDeleteResource()- Explicit soft deleterestoreResource()- Restore soft-deleted resourceforceDeleteResource()- Permanent deletion
Advanced book search functionality:
searchBooks()- Multi-criteria search- Full-text search using Meilisearch
- Filtering by title, author, ISBN, date range
- Sorting and pagination support
Fetches data from external APIs:
fetchExternalResource()- Fetch from single endpoint- Handles authentication (Bearer, API Key, Basic Auth)
- Rate limiting and retry logic
- Field mapping and data transformation
Manages featured book collections:
fetchBooksForSelection()- Get books available for featuringfetchCuratedBooks()- Get current featured booksstoreFeaturedBooks()- Add books to featured collectiondeleteFeaturedBook()- Remove from featured collection
Provides dashboard statistics:
- Total resources count
- Active/inactive resource breakdown
- API vs Redirect resource counts
- System health metrics
| Controller | Purpose | Key Methods |
|---|---|---|
| ResourceController | Resource CRUD operations | index, store, show, update, destroy, updateStatus, updateApiConfig |
| BookManagerController | Book search and management | searchBooks, fetchBooksForFeaturedSelection, storeCuratedFeaturedBooks |
| ApiSyncController | Sync management | syncResource, syncEndpoint, getEndpointStatus, getResourceStatus |
| AuthController | Authentication | login, verify, logout |
| DashboardController | Dashboard data | stats |
| LogController | Log retrieval | getLaravelLog, getInfoLog, getErrorLog, clearAllLogs |
- Syncs individual API endpoint
- Updates sync status (IDLE β SYNCING β COMPLETED/FAILED)
- Handles authentication and rate limiting
- Processes data in chunks
- Automatic retry with exponential backoff
- Processes fetched data chunks
- Stores/updates book records in cache
- Maps fields from external format to internal format
- Handles duplicate detection
- Dispatches sync jobs for all endpoints of a resource
- Orchestrates resource-level synchronization
| Model | Description | Key Relationships |
|---|---|---|
| Resource | Base resource model | hasOne(ApiResource), hasOne(RedirectLink) |
| ApiResource | API configuration | belongsTo(Resource), hasMany(ApiEndpoint) |
| ApiEndpoint | API endpoint details | belongsTo(ApiResource) |
| CacheBook | Cached book data | belongsTo(ApiResource), searchable with Meilisearch |
| FeaturedBook | Featured book references | belongsTo(CacheBook) |
| RedirectLink | External redirect URLs | belongsTo(Resource) |
# Sync API endpoints
php artisan api:sync-endpoints
# Sync specific endpoint
php artisan api:sync-endpoints --endpoint-id=123
# Sync all endpoints for a resource
php artisan api:sync-endpoints --resource-id=456
# Force sync even if already syncing
php artisan api:sync-endpoints --forcefrontend/
βββ src/
β βββ api/ # API service layer
β β βββ ApiService.js
β β βββ ApiSyncService.js
β β βββ ResourceService.js
β β βββ AuthService.js
β β βββ LogService.js
β βββ components/
β β βββ layout/ # Layout components
β β βββ page_components/ # Page-specific components
β β βββ ui/ # Reusable UI components
β βββ contexts/ # React contexts
β β βββ AuthContext.jsx
β βββ hooks/ # Custom React hooks
β β βββ auth/ # Auth hooks
β β βββ books/ # Book hooks
β β βββ dashboard/ # Dashboard hooks
β β βββ resources/ # Resource hooks
β β βββ useNotification.jsx
β βββ pages/ # Page components
β β βββ admin/ # Admin pages
β β βββ SearchPage.jsx
β β βββ SourcePage.jsx
β βββ routes/ # Routing configuration
β β βββ AppRoute.jsx
β β βββ ProtectedRoute.jsx
β βββ utils/ # Utility functions
βββ public/ # Static assets
βββ package.json
-
SearchPage (
/) - Main book search interface- Multi-field search form
- Results with pagination
- Filter by source/resource
- Real-time search with debouncing
-
SourcePage (
/source/:id) - Individual resource detail page- Display resource information
- Redirect to external resource
-
AdminLoginPage (
/admin/login) - Admin authentication- Basic auth login form
- Redirect to dashboard on success
-
AdminDashboard (
/admin/dashboard) - Dashboard overview- System statistics
- Quick action buttons
- Recent activity
-
ResourcePage (
/admin/resources) - Resource management- List all resources with filtering
- Create/edit/delete resources
- Sync controls for API resources
- Real-time sync status
-
FeaturedBooksPage (
/admin/featured-books) - Featured books management- Select books for featuring
- Manage featured collection
- Drag-and-drop reordering
-
LogsPage (
/admin/logs) - System logs viewer- Laravel system logs
- Application info logs
- Error logs
- Log clearing functionality
-
CreateApiResourcePage (
/admin/resources/create/api) - Create API resource- API configuration form
- Endpoint management
- Authentication setup
-
EditApiResourcePage (
/admin/resources/:id/edit) - Edit resource- Update resource details
- Modify endpoints
- Change authentication
-
CreateRedirectResourcePage (
/admin/resources/create/redirect) - Create redirect link- Simple redirect URL setup
- AdminLayout - Admin page wrapper with navigation
- LayoutWrapper - Root layout provider
- ResourceTable - Displays resources in table format
- ResourceCard - Card view for resources
- SyncStatusBadge - Shows sync status with animations
- ResourceFilters - Filter controls for resource list
- Button - Styled button component
- Input - Form input component
- Modal - Modal dialog component
- Toast - Notification toast
- LogoLoading - Loading spinner with logo
// Get all resources with filtering
getActiveApiResources(params, auth)
// Get single resource
getResourceById(id, auth)
// Create resource
createResource(data, auth)
// Update resource
updateResource(id, data, auth)
// Delete resource
deleteResource(id, auth)// Sync all endpoints of a resource
syncResource(resourceId, auth)
// Sync single endpoint
syncEndpoint(endpointId, auth)
// Get endpoint sync status
getEndpointStatus(endpointId, auth)
// Get resource sync status
getResourceStatus(resourceId, auth)// Login
login(username, password)
// Verify token
verify(token)
// Logout
logout(token)useResources()- Fetch resources with React QueryuseCreateResource()- Create resource mutationuseUpdateResource()- Update resource mutationuseDeleteResource()- Delete resource mutationuseSyncResourceMutation()- Sync resourceuseSyncEndpointMutation()- Sync endpointuseResourceSyncStatus()- Poll sync status
useSearchBooks()- Search books with filtersuseFeaturedBooks()- Get featured booksuseStoreFeaturedBooks()- Add featured booksuseDeleteFeaturedBook()- Remove featured book
useAuth()- Access auth contextuseLogin()- Login mutationuseLogout()- Logout mutation
useNotification()- Toast notification systemuseDebounce()- Debounce value changesuseKeyRedirect()- Keyboard shortcut navigation
The application uses:
- React Query for server state (data fetching, caching, synchronization)
- React Context for global state (authentication)
- Local State for component-specific state
http://localhost:8000/api/v1
Most endpoints require Basic Auth:
Authorization: Basic base64(username:password)
| Method | Endpoint | Description |
|---|---|---|
| GET | /resources |
List all resources |
| GET | /resources/{id} |
Get single resource |
| POST | /resources |
Create resource |
| PUT | /resources/{id} |
Update resource |
| PATCH | /resources/{id} |
Partial update |
| DELETE | /resources/{id} |
Delete resource |
| DELETE | /resources/multiple |
Delete multiple resources |
| DELETE | /resources/{id}/soft |
Soft delete resource |
| POST | /resources/{id}/restore |
Restore soft-deleted resource |
| DELETE | /resources/{id}/force |
Force delete resource |
| PATCH | /resources/{id}/status |
Update status only |
| PATCH | /resources/{id}/api-config |
Update API config |
| PATCH | /resources/{id}/endpoints |
Update endpoints |
| PATCH | /resources/{id}/redirect |
Update redirect URL |
?type=API|REDIRECT - Filter by type
&status=ACTIVE|INACTIVE - Filter by status
&per_page=20 - Results per page
&page=1 - Page number
&sort_by=name|created_at - Sort field
&sort_order=asc|desc - Sort direction
| Method | Endpoint | Description |
|---|---|---|
| POST | /sync/resources/{id} |
Sync all endpoints of resource |
| POST | /sync/endpoints/{id} |
Sync single endpoint |
| GET | /sync/endpoints/{id}/status |
Get endpoint sync status |
| GET | /sync/resources/{id}/status |
Get resource sync status |
| Method | Endpoint | Description |
|---|---|---|
| GET | /books/search |
Search books |
| GET | /books/featured/selection |
Get books for featuring |
| GET | /books/featured/curated |
Get current featured books |
| POST | /books/featured/store |
Add featured books |
| DELETE | /books/featured/delete/{id} |
Remove featured book |
?q=search_term - Search query
&title=book_title - Filter by title
&author=author_name - Filter by author
&isbn=isbn_number - Filter by ISBN
&api_resource_id=123 - Filter by resource
&date_from=2020-01-01 - Date range start
&date_to=2024-12-31 - Date range end
&per_page=20 - Results per page
&page=1 - Page number
| Method | Endpoint | Description |
|---|---|---|
| GET | /dashboard/stats |
Get dashboard statistics |
| Method | Endpoint | Description |
|---|---|---|
| GET | /logs/laravel |
Get Laravel log (text/plain) |
| GET | /logs/info |
Get info log (text/plain) |
| GET | /logs/error |
Get error log (text/plain) |
| POST | /logs/laravel/clear |
Clear Laravel log |
| POST | /logs/info/clear |
Clear info log |
| POST | /logs/error/clear |
Clear error log |
| POST | /logs/all/clear |
Clear all logs |
| Method | Endpoint | Description |
|---|---|---|
| POST | /auth/auth/login |
Admin login |
| POST | /auth/auth/verify |
Verify token |
| POST | /auth/auth/logout |
Logout |
All API responses follow this format:
Success Response:
{
"data": { ... },
"message": "Success message",
"success": true,
"status_code": 200
}Error Response:
{
"data": null,
"message": "Error message",
"success": false,
"status_code": 400|404|500,
"error": "Detailed error information"
}Paginated Response:
{
"data": {
"results": [ ... ],
"total_results": 100,
"per_page": 20,
"current_page": 1,
"last_page": 5,
"from": 1,
"to": 20
},
"message": "Resources fetched successfully",
"success": true,
"status_code": 200
}For detailed API documentation with request/response examples, see backend/API_DOCUMENTATION.md
- Search across internal cache and external APIs
- Full-text search with Meilisearch
- Advanced filtering (title, author, ISBN, date range)
- Real-time results with pagination
- Source attribution for each result
- Connect to academic databases (EBSCOhost, JSTOR, ProQuest, ScienceDirect)
- Multiple authentication methods:
- Bearer Token
- API Key (Header/Query Parameter)
- Basic Authentication
- Custom field mapping for data transformation
- Rate limiting and retry logic
- Granular Control: Per-endpoint sync management
- Scheduled Sync: Automatic sync every 30 minutes
- Manual Sync: On-demand sync via UI or CLI
- Status Tracking: Real-time sync status (IDLE, SYNCING, COMPLETED, FAILED)
- Chunked Processing: Process large datasets in manageable chunks
- Error Recovery: Automatic retry with exponential backoff
- Curate featured book collections
- Select from available books
- Display on public-facing pages
- Easy management interface
- System statistics overview
- Resource management interface
- Featured books curation
- Log viewing and management
- Sync status monitoring
- Laravel System Logs: Framework-level logging
- Application Info Logs: Success and information events
- Error Logs: Error tracking and debugging
- Activity Logs: User actions and system events
- Real-time Log Viewer: View logs in admin interface
- Log Clearing: Clean up old log files
- Admin authentication with token-based auth
- Basic Auth for API endpoints
- Protected routes with middleware
- Session management
- Secure password handling
- Database query optimization
- Eager loading of relationships
- Response caching
- Queue-based background processing
- Efficient pagination
- Meilisearch for fast full-text search
- Comprehensive API documentation
- Consistent response format
- Detailed error messages
- Artisan commands for common tasks
- Environment-based configuration
- Database migrations and seeders
Backend:
# 1. Install dependencies
composer install --optimize-autoloader --no-dev
# 2. Configure environment
cp .env.example .env
# Edit .env with production settings
# 3. Generate key and optimize
php artisan key:generate
php artisan config:cache
php artisan route:cache
php artisan view:cache
# 4. Run migrations
php artisan migrate --force
# 5. Set permissions
chmod -R 775 storage bootstrap/cache
chown -R www-data:www-data storage bootstrap/cache
# 6. Start queue workers (use supervisor)
php artisan queue:work --daemon
# 7. Setup scheduler (add to crontab)
* * * * * cd /path-to-project && php artisan schedule:run >> /dev/null 2>&1Frontend:
# 1. Install dependencies
npm install
# 2. Build for production
npm run build
# 3. Deploy dist/ folder to web server
# Configure web server to serve index.html for all routesNginx:
server {
listen 80;
server_name your-domain.com;
root /path/to/ValACE-New-OPAC/backend/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}Backend (.env):
APP_NAME=ValACE
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=valace_db
DB_USERNAME=your_username
DB_PASSWORD=your_password
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=your_master_keyFrontend (.env):
VITE_API_BASE_URL=https://your-domain.com/api/v1Jerry Castrudes
- GitHub: @Soujiro0

