Files
unai/docs/DEVELOPER_GUIDE.md
Krikorios aa459f4bd6 🎉 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!
2025-07-20 08:26:25 +04:00

17 KiB

White-Label University Portal - Developer Guide

📚 Table of Contents

  1. Architecture Overview
  2. Getting Started
  3. API Documentation
  4. Database Schema
  5. Multi-Tenant Architecture
  6. Performance Optimization
  7. Deployment Guide
  8. Testing
  9. Contributing
  10. 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

    git clone https://github.com/your-org/university-portal.git
    cd university-portal
    
  2. Install Dependencies

    npm install
    
  3. Environment Setup

    cp .env.example .env.local
    # Edit .env.local with your configuration
    
  4. Database Setup

    npx prisma generate
    npx prisma db push
    npx prisma db seed
    
  5. Start Development Server

    npm run dev
    

Environment Variables

# 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:

X-University-Id: university-id
X-University-Slug: university-slug

Core Endpoints

Universities

GET /api/universities
POST /api/universities
GET /api/universities/[slug]
PUT /api/universities/[slug]
DELETE /api/universities/[slug]

Content Management

GET /api/content
POST /api/content
GET /api/content/[id]
PUT /api/content/[id]
DELETE /api/content/[id]

Programs

GET /api/programs
POST /api/programs
GET /api/programs/[id]
PUT /api/programs/[id]
DELETE /api/programs/[id]

Domains

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

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:

{
  "success": true,
  "data": {
    // Response data
  },
  "message": "Operation completed successfully",
  "timestamp": "2025-01-01T00:00:00.000Z"
}

Error Handling

{
  "success": false,
  "error": "Error message",
  "code": "ERROR_CODE",
  "timestamp": "2025-01-01T00:00:00.000Z"
}

🗄️ Database Schema

Core Models

University

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

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

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

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

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:

// 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

// 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

// 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

// 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

// 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

// 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

    # Set production environment variables
    export NODE_ENV=production
    export DATABASE_URL="postgresql://..."
    export REDIS_URL="redis://..."
    
  2. Database Migration

    npx prisma migrate deploy
    npx prisma generate
    
  3. Build Application

    npm run build
    

Docker Deployment

# 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"]
# 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

    vercel --prod
    
  3. Custom Domain

    • Add custom domain in Vercel dashboard
    • Configure DNS records

🧪 Testing

Unit Tests

// 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

// 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

// 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

    git clone https://github.com/your-username/university-portal.git
    cd university-portal
    
  2. Create Feature Branch

    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

    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

    # Check database connection
    npx prisma db push
    
    # Reset database
    npx prisma migrate reset
    
  2. Redis Connection

    # Check Redis connection
    redis-cli ping
    
    # Clear cache
    redis-cli flushall
    
  3. Build Issues

    # Clear Next.js cache
    rm -rf .next
    npm run build
    

Debug Mode

# Enable debug logging
DEBUG=* npm run dev

# Database queries
DEBUG=prisma:query npm run dev

# Redis operations
DEBUG=redis npm run dev

Performance Monitoring

// 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

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