Replace
teachlink/backendin the badge URLs above with your actualorg/reposlug once the repository is on GitHub.
TeachLink is a decentralized platform built to enable technocrats to share, analyze, and monetize knowledge, skills, and ideas. This repository contains the backend API built with NestJS, TypeORM, and powered by Starknet and PostgreSQL, serving as the core of the TeachLink ecosystem.
This is the NestJS backend powering TeachLink β offering APIs, authentication, user management, notifications, and knowledge monetization features.
- Pagination is limited to a maximum page size of 100 items per request.
Every pull request and every push to main / develop runs an automated pipeline defined in .github/workflows/ci.yml.
| Stage | Tool | Fails on |
|---|---|---|
| Install | npm ci |
Dependency resolution error |
| Lint | ESLint | Any warning or error (--max-warnings 0) |
| Format | Prettier | Any file that would be reformatted |
| Type Check | tsc --noEmit |
Any TypeScript error |
| Build | NestJS CLI | Compilation failure |
| Unit Tests | Jest + ts-jest | Test failure or coverage below 70 % |
| E2E Tests | Jest + Supertest | Test failure (uses real Postgres + Redis) |
# Lint (auto-fix)
npm run lint
# Lint (CI-strict, no auto-fix)
npm run lint:ci
# Format check (no rewrite)
npm run format:check
# TypeScript type check only
npm run typecheck
# Unit tests with coverage report
npm run test:ci
# E2E tests (requires Postgres + Redis running locally)
npm run test:e2eConfigured in jest.config.js. The pipeline fails if any global metric falls below:
| Metric | Threshold |
|---|---|
| Statements | 70 % |
| Branches | 70 % |
| Functions | 70 % |
| Lines | 70 % |
Coverage HTML report is uploaded as a GitHub Actions artifact (coverage-report) on every run.
Both main and develop are protected. Direct pushes are disabled for everyone including admins.
| Rule | main |
develop |
|---|---|---|
| Required PR approvals | 2 (incl. code owner) | 1 |
| Dismiss stale reviews on new commit | β | β |
| Required status check | CI Passed |
CI Passed |
| Branch must be up to date | β | β |
| All conversations resolved | β | β |
| Squash merge only | β | β |
| Force push | β | β |
| Branch deletion | β | β |
Rules are defined in code in .github/workflows/branch-protection.yml and can be re-applied to any new repository by running the Bootstrap Branch Protection workflow manually from the Actions tab.
For the full contribution and review policy, see CONTRIBUTING.md.
src/
βββ modules/
β βββ auth/ # JWT, session management, wallet login
β βββ users/ # Profile management, roles, preferences
β βββ courses/ # Course creation, enrollment, content
β βββ payments/ # Stripe integration, transactions
β βββ search/ # Elasticsearch integration, search APIs
β βββ notifications/ # Real-time alerts, email, push notifications
β βββ messaging/ # Real-time chat, discussions
β βββ media/ # File upload, processing, CDN
β βββ collaboration/ # Real-time collaboration features
β βββ assessment/ # Quizzes, tests, grading
β βββ learning-paths/ # Personalized learning journeys
β βββ gamification/ # Points, badges, leaderboards
β βββ moderation/ # Content moderation, reporting
β βββ email-marketing/ # Campaign management, templates
β βββ ab-testing/ # Feature experimentation
β βββ data-warehouse/ # Analytics, reporting
β βββ backup/ # Data backup and recovery
β βββ sync/ # Data synchronization
β βββ tenancy/ # Multi-tenant support
β βββ security/ # Security utilities, monitoring
β βββ caching/ # Redis caching strategies
β βββ rate-limiting/ # API rate limiting
β βββ observability/ # Metrics, logging, tracing
β βββ queue/ # Background job processing
β βββ health/ # Health checks, monitoring
βββ common/
β βββ database/ # Database configuration, connection
β βββ decorators/ # Custom decorators
β βββ guards/ # Authentication & authorization guards
β βββ interceptors/ # Request/response interceptors
β βββ pipes/ # Data validation pipes
β βββ dto/ # Data transfer objects
β βββ utils/ # Utility functions
βββ config/ # Environment configuration
βββ graphql/ # GraphQL schemas and resolvers
βββ main.ts # Application entry point
TeachLink Backend provides secure and scalable APIs to power features such as:
- π§Ύ Post creation, editing, and markdown parsing
- π§ Topic discovery and categorization
- π₯ User account management with wallet login
- πΈ On-chain tipping and transaction logging
- ποΈ Gamified reputation and contribution tracking
- π Real-time notifications via WebSockets
- π Analytics and activity insights
- π§Ύ DAO integration for content moderation and governance
TeachLink uses a header-based API versioning strategy for application endpoints.
- Send
X-API-Version: 1with every versioned API request. - Supported versions are configured through
API_SUPPORTED_VERSIONSand default to1. API_DEFAULT_VERSIONcontrols the currently active route version and defaults to1.- Health checks, metrics endpoints, the root route, and payment webhooks are version-neutral.
- Requests with a missing or invalid API version header return a client error before the request reaches the controller.
Example:
curl -H "X-API-Version: 1" http://localhost:3000/users| Layer | Technology |
|---|---|
| Framework | NestJS |
| Database | PostgreSQL + TypeORM |
| Blockchain | Starknet + Starknet.js |
| Realtime | WebSockets (Gateway) |
| Queues/Async | BullMQ + Redis (optional) |
| File Uploads | Cloudinary |
| Config Mgmt | @nestjs/config |
| Testing | Jest + Supertest |
| Auth | JWT + Wallet Sign-In |
| Deployment | Docker, Railway, or Fly.io |
| File Upload | Cloudinary |
| Security | Helmet + bcrypt |
TeachLink Backend follows a modular microservices architecture built on NestJS, designed for scalability and maintainability. The system uses a layered approach with clear separation of concerns:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β API Gateway Layer β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
β β REST API β β GraphQL β β WebSocket Gateway β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Business Logic Layer β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
β β Auth β β Users β β Courses β β
β β Module β β Module β β Module β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
β β Payments β β Search β β Notifications β β
β β Module β β Module β β Module β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Infrastructure Layer β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
β β PostgreSQL β β Redis β β File Storage β β
β β (Primary) β β (Caching) β β (AWS S3) β β
β βββββββββββββββ βββββββββββββββ βββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Modular Design: Each business domain is encapsulated in its own module
- Dependency Injection: Leverages NestJS DI for loose coupling
- Repository Pattern: Data access abstraction via TypeORM
- Event-Driven Architecture: Uses EventEmitter for inter-module communication
- CQRS Pattern: Separation of read/write operations in complex modules
- Feature Flags: Dynamic module loading based on configuration
- Request Processing: API Gateway β Authentication β Authorization β Business Logic
- Data Persistence: Business Logic β Repository β PostgreSQL
- Caching Strategy: Redis for frequently accessed data and session management
- Async Operations: BullMQ for background jobs and email processing
- File Handling: AWS S3/Cloudinary for media storage with CDN distribution
| Layer | Technology | Purpose |
|---|---|---|
| Framework | NestJS | Node.js application framework |
| Language | TypeScript | Type-safe JavaScript |
| Database | PostgreSQL + TypeORM | Primary data storage |
| Caching | Redis + IORedis | Session store, caching, queues |
| Authentication | JWT + Passport | Token-based authentication |
| GraphQL | Apollo Server | GraphQL API (optional) |
| Real-time | Socket.io | WebSocket connections |
| File Storage | AWS S3 + Cloudinary | Media file storage and CDN |
| SendGrid + Nodemailer | Email delivery and marketing | |
| Payments | Stripe | Payment processing |
| Search | Elasticsearch | Full-text search capabilities |
| Queue | BullMQ | Background job processing |
| Monitoring | OpenTelemetry + Prometheus | Metrics and observability |
| Testing | Jest + Supertest | Unit and integration tests |
| Documentation | Swagger | API documentation |
| Validation | class-validator + class-transformer | DTO validation |
| Security | Helmet + bcrypt | Security headers and password hashing |
The application uses bcrypt for password hashing with configurable rounds via the BCRYPT_ROUNDS environment variable.
| Environment | Recommended Rounds | Hash Time (ms) | Security Level | Performance Impact |
|---|---|---|---|---|
| Development | 8-10 | 50-100 | Good | Low |
| Staging | 10-12 | 100-300 | High | Medium |
| Production | 12-14 | 300-1000 | Very High | High |
Lower Rounds (4-8):
- β Faster authentication
- β Lower CPU usage
β οΈ Reduced security against brute force attacksβ οΈ May be vulnerable to GPU-based cracking
Higher Rounds (12-15):
- β Strong resistance against brute force attacks
- β Future-proof against computational advances
- β Slower authentication (may impact user experience)
- β Higher CPU usage (may affect scalability)
# Development (faster, less secure)
BCRYPT_ROUNDS=8
# Production (slower, more secure)
BCRYPT_ROUNDS=12- Minimum 10 rounds for production environments
- Monitor authentication performance when increasing rounds
- Consider rate limiting to prevent brute force attacks
- Use hardware security modules for high-security applications
- Regular security audits to assess adequate protection levels
When changing BCRYPT_ROUNDS:
- Existing passwords remain valid until users change them
- New passwords will use the configured rounds
- Consider forcing password reset for sensitive accounts
- Gradually increase rounds to monitor performance impact
The application uses strategic database indexes to optimize query performance, especially for frequently accessed data and pagination operations.
- User.email: Unique index for authentication lookups
- User.username: Index for profile searches
- User.tenantId: Index for multi-tenant queries
- Payment.status: Index for payment status filtering
- Payment.userId: Index for user payment history
- Payment.courseId: Index for course revenue queries
- Subscription.status: Index for active subscription queries
- Subscription.userId: Index for user subscription management
- Course.status: Index for published course listings
- Course.instructorId: Index for instructor course queries
- Enrollment.userId: Index for user enrollment history
- Enrollment.courseId: Index for course enrollment counts
- Enrollment.status: Index for active enrollment filtering
- CourseModule.courseId: Index for course module queries
- Lesson.moduleId: Index for module lesson queries
- Enrollment (userId, status): Optimized for user enrollment status queries
- Enrollment (courseId, status): Optimized for course enrollment analytics
- Payment (userId, status): Optimized for user payment status filtering
- Subscription (userId, status): Optimized for user subscription status queries
- Indexes are added to foreign key columns to improve JOIN performance
- Composite indexes support common query patterns (e.g., filtering by user + status)
- Partial indexes are used where applicable for better selectivity
- Index maintenance overhead is monitored to ensure write performance is not negatively impacted
The backend supports explicit database pool tuning through environment variables:
DATABASE_POOL_MAX(default:30)DATABASE_POOL_MIN(default:5)DATABASE_POOL_ACQUIRE_TIMEOUT_MS(default:10000)DATABASE_POOL_IDLE_TIMEOUT_MS(default:30000)
Recommended starting points:
| Environment | DATABASE_POOL_MAX |
DATABASE_POOL_MIN |
Acquire Timeout | Idle Timeout |
|---|---|---|---|---|
| Development | 10 | 2 | 5000 ms | 10000 ms |
| Staging | 20 | 5 | 10000 ms | 30000 ms |
| Production | 30 to 60 | 5 to 10 | 10000 ms | 30000 ms |
Sizing rule:
- Keep total active connections across workers below PostgreSQL capacity.
- Formula:
DATABASE_POOL_MAX x app_instances x cluster_workers <= postgres_max_connections - reserved_connections. - Reserve at least 20 to 30 connections for migrations, admin access, and background jobs.
- Node.js 18+ with npm
- PostgreSQL 14+ (or Docker)
- Redis 6+ (for caching and queues)
- Git for version control
- Clone the repository
git clone https://github.com/teachlink/backend.git
cd teachlink_backend- Install dependencies
npm install- Set up environment variables
cp .env.example .env
# Edit .env with your configuration- Start PostgreSQL and Redis
# Using Docker (recommended)
docker-compose up -d postgres redis
# Or install locally and start services
# PostgreSQL: sudo systemctl start postgresql
# Redis: sudo systemctl start redis- Run database migrations
npm run typeorm migration:run- Start the development server
npm run start:dev- Access the API
- REST API: http://localhost:3000
- API Documentation: http://localhost:3000/api
- Health Check: http://localhost:3000/health
Key environment variables to configure:
# Database
DATABASE_HOST=localhost
DATABASE_PORT=5432
DATABASE_USER=postgres
DATABASE_PASSWORD=yourpassword
DATABASE_NAME=teachlink
# Authentication
JWT_SECRET=your-super-secret-jwt-key
ENCRYPTION_SECRET=your-32-char-encryption-key
# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
# External Services (Optional)
STRIPE_SECRET_KEY=your_stripe_key
AWS_ACCESS_KEY_ID=your_aws_key
AWS_SECRET_ACCESS_KEY=your_aws_secretFor complete development environment with Docker:
# Start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose downWe welcome contributions from the community! Please follow our guidelines to ensure a smooth contribution process.
- Fork the repository and clone locally
- Set up your environment using
.env.example - Create a feature branch from
develop - Make your changes following our coding standards
- Run tests locally to ensure everything works
- Submit a pull request with a clear description
- Use conventional commits (feat:, fix:, docs:, etc.)
- Follow TypeScript best practices
- Write unit tests for new features
- Update documentation as needed
- Ensure linting and formatting pass
- Linked issue (
Closes #issue_number) - Clear title and description
- Tests pass locally (
npm run test:ci) - Code follows style guidelines (
npm run lint:ci) - Documentation updated if applicable
- π Documentation
- π¬ Telegram Community
- π Report Issues
MIT Β© 2025 TeachLink DAO