🎉 Complete AI-Enhanced University Portal - Ready for Production
✨ Major Features Added: - AI Chat with conversation memory and university-specific knowledge base - Multi-tenant university support with white-label capabilities - Professional admin interface for knowledge base management - Advanced database schema with Prisma ORM - Comprehensive documentation and guides - Modern Next.js 15 + React 19 architecture - Bilingual support (English/Arabic) - Role-based access control - Real-time chat interface with loading states 🔧 Technical Improvements: - Fixed all linter errors and TypeScript issues - Cleaned up codebase and removed legacy files - Added comprehensive .gitignore - Updated README with detailed setup instructions - Optimized database schema and migrations - Enhanced error handling and user experience 📚 Documentation: - AI Conversation Memory Guide - AI Enhancement Summary - Developer Guide - User Guide - Complete setup and deployment instructions 🚀 Ready for GitHub deployment and production use!
This commit is contained in:
@@ -0,0 +1,818 @@
|
||||
# White-Label University Portal - Developer Guide
|
||||
|
||||
## 📚 Table of Contents
|
||||
|
||||
1. [Architecture Overview](#architecture-overview)
|
||||
2. [Getting Started](#getting-started)
|
||||
3. [API Documentation](#api-documentation)
|
||||
4. [Database Schema](#database-schema)
|
||||
5. [Multi-Tenant Architecture](#multi-tenant-architecture)
|
||||
6. [Performance Optimization](#performance-optimization)
|
||||
7. [Deployment Guide](#deployment-guide)
|
||||
8. [Testing](#testing)
|
||||
9. [Contributing](#contributing)
|
||||
10. [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Architecture Overview
|
||||
|
||||
### Technology Stack
|
||||
|
||||
- **Frontend**: Next.js 14, React 19, TypeScript, Tailwind CSS
|
||||
- **Backend**: Next.js API Routes, Prisma ORM
|
||||
- **Database**: PostgreSQL (primary), Redis (caching)
|
||||
- **AI**: OpenRouter AI integration
|
||||
- **CDN**: Multi-provider support (AWS S3, Cloudflare, Cloudinary)
|
||||
- **Deployment**: Vercel, Docker, Kubernetes
|
||||
|
||||
### System Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Frontend │ │ API Layer │ │ Database │
|
||||
│ (Next.js) │◄──►│ (Next.js) │◄──►│ (PostgreSQL) │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ CDN Layer │ │ Cache Layer │ │ AI Services │
|
||||
│ (Multi-CDN) │ │ (Redis) │ │ (OpenRouter) │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
```
|
||||
|
||||
### Multi-Tenant Design
|
||||
|
||||
The platform uses a **database-per-tenant** approach with shared application code:
|
||||
|
||||
- **Data Isolation**: Each university's data is completely isolated
|
||||
- **Shared Infrastructure**: Common codebase and infrastructure
|
||||
- **Dynamic Configuration**: University-specific settings and branding
|
||||
- **Scalable Architecture**: Horizontal scaling support
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Node.js**: 18.x or higher
|
||||
- **PostgreSQL**: 14.x or higher
|
||||
- **Redis**: 6.x or higher
|
||||
- **Git**: Latest version
|
||||
- **Docker**: (optional, for containerized development)
|
||||
|
||||
### Installation
|
||||
|
||||
1. **Clone the Repository**
|
||||
```bash
|
||||
git clone https://github.com/your-org/university-portal.git
|
||||
cd university-portal
|
||||
```
|
||||
|
||||
2. **Install Dependencies**
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. **Environment Setup**
|
||||
```bash
|
||||
cp .env.example .env.local
|
||||
# Edit .env.local with your configuration
|
||||
```
|
||||
|
||||
4. **Database Setup**
|
||||
```bash
|
||||
npx prisma generate
|
||||
npx prisma db push
|
||||
npx prisma db seed
|
||||
```
|
||||
|
||||
5. **Start Development Server**
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
|
||||
```env
|
||||
# Database
|
||||
DATABASE_URL="postgresql://user:password@localhost:5432/university_portal"
|
||||
|
||||
# Redis
|
||||
REDIS_HOST="localhost"
|
||||
REDIS_PORT="6379"
|
||||
REDIS_PASSWORD=""
|
||||
REDIS_DB="0"
|
||||
|
||||
# AI Services
|
||||
OPENROUTER_API_KEY="your-api-key"
|
||||
OPENROUTER_BASE_URL="https://openrouter.ai/api/v1"
|
||||
|
||||
# CDN Configuration
|
||||
AWS_ACCESS_KEY_ID="your-access-key"
|
||||
AWS_SECRET_ACCESS_KEY="your-secret-key"
|
||||
AWS_REGION="us-east-1"
|
||||
AWS_S3_BUCKET="your-bucket"
|
||||
|
||||
# Application
|
||||
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
||||
NEXTAUTH_SECRET="your-secret"
|
||||
NEXTAUTH_URL="http://localhost:3000"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📡 API Documentation
|
||||
|
||||
### Authentication
|
||||
|
||||
All API endpoints require university context via headers:
|
||||
|
||||
```http
|
||||
X-University-Id: university-id
|
||||
X-University-Slug: university-slug
|
||||
```
|
||||
|
||||
### Core Endpoints
|
||||
|
||||
#### Universities
|
||||
|
||||
```http
|
||||
GET /api/universities
|
||||
POST /api/universities
|
||||
GET /api/universities/[slug]
|
||||
PUT /api/universities/[slug]
|
||||
DELETE /api/universities/[slug]
|
||||
```
|
||||
|
||||
#### Content Management
|
||||
|
||||
```http
|
||||
GET /api/content
|
||||
POST /api/content
|
||||
GET /api/content/[id]
|
||||
PUT /api/content/[id]
|
||||
DELETE /api/content/[id]
|
||||
```
|
||||
|
||||
#### Programs
|
||||
|
||||
```http
|
||||
GET /api/programs
|
||||
POST /api/programs
|
||||
GET /api/programs/[id]
|
||||
PUT /api/programs/[id]
|
||||
DELETE /api/programs/[id]
|
||||
```
|
||||
|
||||
#### Domains
|
||||
|
||||
```http
|
||||
GET /api/domains
|
||||
POST /api/domains
|
||||
GET /api/domains/[id]
|
||||
PUT /api/domains/[id]
|
||||
DELETE /api/domains/[id]
|
||||
POST /api/domains/[id]/validate
|
||||
POST /api/domains/[id]/renew-ssl
|
||||
```
|
||||
|
||||
#### Deployments
|
||||
|
||||
```http
|
||||
GET /api/deployments
|
||||
POST /api/deployments
|
||||
GET /api/deployments/[id]
|
||||
POST /api/deployments/[id]/execute
|
||||
POST /api/deployments/[id]/rollback
|
||||
```
|
||||
|
||||
### Response Format
|
||||
|
||||
All API responses follow a consistent format:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
// Response data
|
||||
},
|
||||
"message": "Operation completed successfully",
|
||||
"timestamp": "2025-01-01T00:00:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error": "Error message",
|
||||
"code": "ERROR_CODE",
|
||||
"timestamp": "2025-01-01T00:00:00.000Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ Database Schema
|
||||
|
||||
### Core Models
|
||||
|
||||
#### University
|
||||
```prisma
|
||||
model University {
|
||||
id String @id @default(uuid())
|
||||
slug String @unique
|
||||
name String
|
||||
shortName String?
|
||||
domain String?
|
||||
subdomain String?
|
||||
branding Json
|
||||
contact Json
|
||||
features Json
|
||||
ai Json
|
||||
status UniversityStatus @default(ACTIVE)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
// Relations
|
||||
assets UniversityAsset[]
|
||||
content UniversityContent[]
|
||||
programs AcademicProgram[]
|
||||
knowledge AIKnowledgeBase[]
|
||||
domains DomainConfig[]
|
||||
deployments DeploymentConfig[]
|
||||
cdnConfig CDNConfig?
|
||||
cdnAssets CDNAsset[]
|
||||
}
|
||||
```
|
||||
|
||||
#### UniversityContent
|
||||
```prisma
|
||||
model UniversityContent {
|
||||
id String @id @default(uuid())
|
||||
universityId String
|
||||
title String
|
||||
content String
|
||||
contentType ContentType
|
||||
language Language @default(ENGLISH)
|
||||
isPublished Boolean @default(false)
|
||||
metadata Json?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
```
|
||||
|
||||
#### AcademicProgram
|
||||
```prisma
|
||||
model AcademicProgram {
|
||||
id String @id @default(uuid())
|
||||
universityId String
|
||||
title String
|
||||
description String
|
||||
level ProgramLevel
|
||||
duration String
|
||||
fees Json?
|
||||
requirements Json?
|
||||
isActive Boolean @default(true)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
}
|
||||
```
|
||||
|
||||
### Domain Management
|
||||
|
||||
#### DomainConfig
|
||||
```prisma
|
||||
model DomainConfig {
|
||||
id String @id @default(uuid())
|
||||
universityId String
|
||||
type DomainType
|
||||
domain String
|
||||
subdomain String?
|
||||
sslStatus SSLStatus @default(PENDING)
|
||||
sslExpiryDate DateTime?
|
||||
dnsStatus DNSStatus @default(PENDING)
|
||||
isActive Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
university University @relation(fields: [universityId], references: [id], onDelete: Cascade)
|
||||
sslConfig SSLConfig?
|
||||
dnsConfig DNSConfig?
|
||||
analytics DomainAnalytics[]
|
||||
}
|
||||
```
|
||||
|
||||
### Enums
|
||||
|
||||
```prisma
|
||||
enum UniversityStatus {
|
||||
ACTIVE
|
||||
INACTIVE
|
||||
SUSPENDED
|
||||
}
|
||||
|
||||
enum ContentType {
|
||||
ABOUT
|
||||
NEWS
|
||||
EVENTS
|
||||
RESEARCH
|
||||
CAMPUS
|
||||
}
|
||||
|
||||
enum Language {
|
||||
ENGLISH
|
||||
ARABIC
|
||||
}
|
||||
|
||||
enum ProgramLevel {
|
||||
UNDERGRADUATE
|
||||
POSTGRADUATE
|
||||
PHD
|
||||
}
|
||||
|
||||
enum DomainType {
|
||||
SUBDOMAIN
|
||||
CUSTOM_DOMAIN
|
||||
}
|
||||
|
||||
enum SSLStatus {
|
||||
PENDING
|
||||
ACTIVE
|
||||
EXPIRED
|
||||
ERROR
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏢 Multi-Tenant Architecture
|
||||
|
||||
### Data Isolation
|
||||
|
||||
The platform ensures complete data isolation between universities:
|
||||
|
||||
```typescript
|
||||
// Data isolation middleware
|
||||
export async function validateUniversityAccess(request: NextRequest): Promise<UniversityContext> {
|
||||
const university = getUniversityFromHeaders(request);
|
||||
|
||||
if (!university) {
|
||||
throw new Error('University context required');
|
||||
}
|
||||
|
||||
// Verify university exists and is active
|
||||
const dbUniversity = await prisma.university.findUnique({
|
||||
where: { id: university.id, status: 'ACTIVE' },
|
||||
});
|
||||
|
||||
if (!dbUniversity) {
|
||||
throw new Error('University not found or inactive');
|
||||
}
|
||||
|
||||
return university;
|
||||
}
|
||||
```
|
||||
|
||||
### University Context
|
||||
|
||||
```typescript
|
||||
// University provider for React components
|
||||
export function UniversityProvider({ children, initialUniversity }: UniversityProviderProps) {
|
||||
const [university, setUniversity] = useState<University | null>(initialUniversity);
|
||||
|
||||
// Load university data based on cookies or headers
|
||||
const loadUniversity = async () => {
|
||||
const response = await fetch('/api/universities/current');
|
||||
const data = await response.json();
|
||||
setUniversity(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<UniversityContext.Provider value={{ university, setUniversity }}>
|
||||
{children}
|
||||
</UniversityContext.Provider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Dynamic Branding
|
||||
|
||||
```typescript
|
||||
// Dynamic branding component
|
||||
export function DynamicBranding() {
|
||||
const { university } = useUniversity();
|
||||
|
||||
if (!university) return null;
|
||||
|
||||
const { branding } = university;
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
'--primary-color': branding.primaryColor,
|
||||
'--secondary-color': branding.secondaryColor,
|
||||
} as React.CSSProperties}>
|
||||
<img src={branding.logo} alt={university.name} />
|
||||
<h1>{university.name}</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚡ Performance Optimization
|
||||
|
||||
### Caching Strategy
|
||||
|
||||
```typescript
|
||||
// Redis caching implementation
|
||||
export class CacheManager {
|
||||
async getUniversity(slug: string): Promise<any> {
|
||||
const cacheKey = `university:${slug}`;
|
||||
|
||||
// Try cache first
|
||||
const cached = await this.client.get(cacheKey);
|
||||
if (cached) {
|
||||
return JSON.parse(cached);
|
||||
}
|
||||
|
||||
// Query database
|
||||
const university = await prisma.university.findUnique({
|
||||
where: { slug },
|
||||
include: { assets: true, programs: true }
|
||||
});
|
||||
|
||||
// Cache result
|
||||
if (university) {
|
||||
await this.client.setEx(cacheKey, 1800, JSON.stringify(university));
|
||||
}
|
||||
|
||||
return university;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Query Optimization
|
||||
|
||||
```typescript
|
||||
// Optimized database queries
|
||||
export class QueryOptimizer {
|
||||
async getPrograms(universityId: string, options: any) {
|
||||
const { page = 1, limit = 10, search } = options;
|
||||
const skip = (page - 1) * limit;
|
||||
|
||||
const where = {
|
||||
universityId,
|
||||
isActive: true,
|
||||
...(search && {
|
||||
OR: [
|
||||
{ title: { contains: search, mode: 'insensitive' } },
|
||||
{ description: { contains: search, mode: 'insensitive' } },
|
||||
],
|
||||
}),
|
||||
};
|
||||
|
||||
// Parallel queries for better performance
|
||||
const [programs, total] = await Promise.all([
|
||||
prisma.academicProgram.findMany({ where, skip, take: limit }),
|
||||
prisma.academicProgram.count({ where }),
|
||||
]);
|
||||
|
||||
return { programs, total, page, totalPages: Math.ceil(total / limit) };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CDN Integration
|
||||
|
||||
```typescript
|
||||
// Multi-provider CDN support
|
||||
export class CDNManager {
|
||||
async uploadAsset(file: File, path: string): Promise<CDNAsset> {
|
||||
const config = await this.getCDNConfig();
|
||||
|
||||
let cdnUrl: string;
|
||||
|
||||
switch (config.provider) {
|
||||
case 'AWS_S3':
|
||||
cdnUrl = await this.uploadToS3(file, path, config);
|
||||
break;
|
||||
case 'CLOUDFLARE':
|
||||
cdnUrl = await this.uploadToCloudflare(file, path, config);
|
||||
break;
|
||||
case 'CLOUDINARY':
|
||||
cdnUrl = await this.uploadToCloudinary(file, path, config);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unsupported CDN provider');
|
||||
}
|
||||
|
||||
return { originalPath: path, cdnUrl, optimizedUrls: {} };
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Deployment Guide
|
||||
|
||||
### Environment Setup
|
||||
|
||||
1. **Production Environment**
|
||||
```bash
|
||||
# Set production environment variables
|
||||
export NODE_ENV=production
|
||||
export DATABASE_URL="postgresql://..."
|
||||
export REDIS_URL="redis://..."
|
||||
```
|
||||
|
||||
2. **Database Migration**
|
||||
```bash
|
||||
npx prisma migrate deploy
|
||||
npx prisma generate
|
||||
```
|
||||
|
||||
3. **Build Application**
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Docker Deployment
|
||||
|
||||
```dockerfile
|
||||
# Dockerfile
|
||||
FROM node:18-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm ci --only=production
|
||||
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
CMD ["npm", "start"]
|
||||
```
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
version: '3.8'
|
||||
services:
|
||||
app:
|
||||
build: .
|
||||
ports:
|
||||
- "3000:3000"
|
||||
environment:
|
||||
- DATABASE_URL=${DATABASE_URL}
|
||||
- REDIS_URL=${REDIS_URL}
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
|
||||
postgres:
|
||||
image: postgres:14
|
||||
environment:
|
||||
POSTGRES_DB: university_portal
|
||||
POSTGRES_USER: ${DB_USER}
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
|
||||
redis:
|
||||
image: redis:6-alpine
|
||||
```
|
||||
|
||||
### Vercel Deployment
|
||||
|
||||
1. **Connect Repository**
|
||||
- Link your GitHub repository to Vercel
|
||||
- Configure environment variables
|
||||
|
||||
2. **Deploy**
|
||||
```bash
|
||||
vercel --prod
|
||||
```
|
||||
|
||||
3. **Custom Domain**
|
||||
- Add custom domain in Vercel dashboard
|
||||
- Configure DNS records
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Unit Tests
|
||||
|
||||
```typescript
|
||||
// Example unit test
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { CacheManager } from '../lib/cache';
|
||||
|
||||
describe('CacheManager', () => {
|
||||
it('should cache and retrieve university data', async () => {
|
||||
const cache = new CacheManager(config);
|
||||
const university = { id: '1', name: 'Test University' };
|
||||
|
||||
await cache.set('university:test', university);
|
||||
const retrieved = await cache.get('university:test');
|
||||
|
||||
expect(retrieved).toEqual(university);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Integration Tests
|
||||
|
||||
```typescript
|
||||
// Example integration test
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { createMocks } from 'node-mocks-http';
|
||||
import handler from '../pages/api/universities';
|
||||
|
||||
describe('/api/universities', () => {
|
||||
it('should return universities list', async () => {
|
||||
const { req, res } = createMocks({
|
||||
method: 'GET',
|
||||
headers: { 'x-university-id': 'test-university' },
|
||||
});
|
||||
|
||||
await handler(req, res);
|
||||
|
||||
expect(res._getStatusCode()).toBe(200);
|
||||
expect(JSON.parse(res._getData())).toHaveProperty('data');
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Load Testing
|
||||
|
||||
```typescript
|
||||
// Example load test
|
||||
import { LoadTester } from '../lib/loadTesting';
|
||||
|
||||
const config = {
|
||||
name: 'API Load Test',
|
||||
duration: 300,
|
||||
users: 50,
|
||||
targetRPS: 10,
|
||||
scenarios: [
|
||||
{
|
||||
name: 'Get Universities',
|
||||
weight: 100,
|
||||
requests: [
|
||||
{
|
||||
method: 'GET',
|
||||
url: '/api/universities',
|
||||
expectedStatus: 200,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const tester = new LoadTester(config);
|
||||
const results = await tester.run();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
### Development Workflow
|
||||
|
||||
1. **Fork the Repository**
|
||||
```bash
|
||||
git clone https://github.com/your-username/university-portal.git
|
||||
cd university-portal
|
||||
```
|
||||
|
||||
2. **Create Feature Branch**
|
||||
```bash
|
||||
git checkout -b feature/your-feature-name
|
||||
```
|
||||
|
||||
3. **Make Changes**
|
||||
- Follow the coding standards
|
||||
- Add tests for new features
|
||||
- Update documentation
|
||||
|
||||
4. **Submit Pull Request**
|
||||
```bash
|
||||
git push origin feature/your-feature-name
|
||||
# Create PR on GitHub
|
||||
```
|
||||
|
||||
### Coding Standards
|
||||
|
||||
- **TypeScript**: Strict mode enabled
|
||||
- **ESLint**: Airbnb configuration
|
||||
- **Prettier**: Consistent formatting
|
||||
- **Conventional Commits**: Standard commit messages
|
||||
|
||||
### Code Review Process
|
||||
|
||||
1. **Automated Checks**
|
||||
- Linting and formatting
|
||||
- Type checking
|
||||
- Unit tests
|
||||
- Integration tests
|
||||
|
||||
2. **Manual Review**
|
||||
- Code quality review
|
||||
- Security review
|
||||
- Performance review
|
||||
|
||||
3. **Approval**
|
||||
- At least 2 approvals required
|
||||
- All checks must pass
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Database Connection**
|
||||
```bash
|
||||
# Check database connection
|
||||
npx prisma db push
|
||||
|
||||
# Reset database
|
||||
npx prisma migrate reset
|
||||
```
|
||||
|
||||
2. **Redis Connection**
|
||||
```bash
|
||||
# Check Redis connection
|
||||
redis-cli ping
|
||||
|
||||
# Clear cache
|
||||
redis-cli flushall
|
||||
```
|
||||
|
||||
3. **Build Issues**
|
||||
```bash
|
||||
# Clear Next.js cache
|
||||
rm -rf .next
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
|
||||
```bash
|
||||
# Enable debug logging
|
||||
DEBUG=* npm run dev
|
||||
|
||||
# Database queries
|
||||
DEBUG=prisma:query npm run dev
|
||||
|
||||
# Redis operations
|
||||
DEBUG=redis npm run dev
|
||||
```
|
||||
|
||||
### Performance Monitoring
|
||||
|
||||
```typescript
|
||||
// Monitor query performance
|
||||
const queryOptimizer = getQueryOptimizer();
|
||||
const stats = queryOptimizer.getQueryStats();
|
||||
console.log('Query Statistics:', stats);
|
||||
|
||||
// Monitor cache performance
|
||||
const cache = getCacheInstance();
|
||||
const cacheStats = await cache.getStats();
|
||||
console.log('Cache Statistics:', cacheStats);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📞 Support
|
||||
|
||||
### Getting Help
|
||||
|
||||
- **Documentation**: This developer guide
|
||||
- **Issues**: GitHub Issues
|
||||
- **Discussions**: GitHub Discussions
|
||||
- **Email**: dev-support@your-domain.com
|
||||
|
||||
### Resources
|
||||
|
||||
- **API Reference**: `/api/docs`
|
||||
- **Database Schema**: `prisma/schema.prisma`
|
||||
- **Component Library**: Storybook documentation
|
||||
- **Performance Dashboard**: `/admin/performance`
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: January 2025
|
||||
**Version**: 1.0
|
||||
**Platform**: White-Label University Portal
|
||||
Reference in New Issue
Block a user