Skip to content

Repository files navigation

DevFlow Backend API

The core engine powering DevFlow's interactive coding and AI mentoring platform.

πŸ”— View the Frontend Repository

Node.js Express.js TypeScript MongoDB Redis Docker GitHub Actions


πŸ“– Table of Contents

Overview

The DevFlow Backend API serves as the central nervous system bridging the user's interactive code editor with the AI mentoring engine. It's a robust, stateless Node.js application built with Express and TypeScript, designed to handle high-frequency interactions like real-time workspace auto-saving and low-latency code evaluations.

By offloading state management to a unified Redis cache and isolating core learning data in MongoDB, the architecture ensures resilient scaling. Crucially, the backend acts as a secure gateway to the Gemini AI models, orchestrating prompts, validating context, and strictly enforcing guardrails to provide Socratic guidance rather than spoon-fed code solutions.

Tech Stack

  • Runtime/Framework: Node.js (v20), Express (v5)
  • Language: TypeScript
  • Database & ORM: MongoDB (v7), Mongoose (v9)
  • Caching & Rate Limiting: Redis, ioredis, rate-limit-redis
  • AI Engine: Google Generative AI SDK (Gemini 2.5 Flash)
  • Security & Validation: helmet, bcrypt, jsonwebtoken, zod

Features

  • AI Mentoring Engine: Seamlessly integrates with Gemini 2.5 Flash, actively preventing spoon-feeding by employing prompt sandwiching and post-generation regex output sanitization.
  • Explain-to-Pass Verification: A specialized module that grades users' logical explanations of their code using AI heuristics before allowing progression.
  • High-Frequency Auto-Save Workspace: Manages highly mutable user code workspaces using robust rate limiting, persisting incremental file modifications to the database asynchronously.
  • Mastery-Based Progression State: Secures the sequential unlocking roadmap, ensuring that learners cannot skip prerequisites, while also tracking daily learning streaks.
  • Secure Authentication & Identity: Utilizes JSON Web Tokens (JWT) utilizing a dual-token mechanism (short-lived access tokens and refresh tokens stored securely in HTTP-only cookies) coupled with standard email/password flows to manage stateless sessions securely.

Project Architecture

The backend utilizes a scalable, stateless MVC (Model-View-Controller) pattern augmented with specialized Service layers for business logic and AI orchestration. Redis is heavily leveraged as a shared state manager, driving the 5-Tier Rate Limiting system to prevent abuse of our AI models and database. For AI context, the backend dynamically queries decoupled collections (AI_CHATS, AI_HINTS) to construct sliding window context histories, ensuring the mentor remains aware of previous student interactions while strictly bounding token usage.

Security & Guardrails

1. Redis-Backed Rate Limiting (5-Tier)

Our backend implements a tiered defense mechanism using express-rate-limit and ioredis to prevent abuse:

  • Global Limiter (rl:global:): 1000 requests per 15 minutes window for all general API traffic.
  • Auth Limiter (rl:auth:): Strict 5 attempts per 5 minutes to mitigate brute-force logins.
  • AI Limiter (rl:ai:): 50 requests per 60 minutes, keyed by User ID to enforce hourly AI quotas.
  • Auto-Save Limiter (rl:autosave:): 30 requests per 10 seconds, allowing for frequent typing saves without overloading the DB.
  • Export Limiter (rl:export:): 5 requests per 5 minutes for heavy payload generation.

2. Prompt Injection Defenses

To ensure the AI acts as a mentor and not a code-generator, we employ three defensive layers within our AI services:

  • XML Quarantine: User input is strictly wrapped inside <student_message> tags to isolate it from system instructions.
  • The Sandwich Method: System re-enforcement instructions ("Do NOT provide full code solutions...") are forcibly appended after the user's quarantined input to ensure they are evaluated last.
  • Regex Output Sanitization: AI responses are intercepted using a code block regex. If the model ignores instructions and generates a code block exceeding 4 lines, the entire response is scrubbed and replaced with a default conceptual hint. Additionally, chat output tokens are strictly hard-capped at 400.

API Documentation

Method Endpoint Description Guardrail Middleware
POST /api/auth/login Authenticates user and returns JWT authLimiter
GET /api/project/:slug Retrieves project overview & details cacheResponse(1h)
PUT /api/workspace/file Auto-saves user file modifications protect, autoSaveLimiter
POST /api/workspace/complete-task Submits a task for completion protect
POST /api/ai/chat/message Contextual AI chat message protect, aiRateLimiter
POST /api/ai/explain-to-pass Evaluates student code explanation protect, aiRateLimiter
GET /api/user/profile Fetches aggregated profile data protect

CI/CD & Deployments

The backend utilizes GitHub Actions for its CI pipeline, triggering on pushes and pull requests to the main branch. It automatically sets up Node.js v20, installs dependencies cleanly with npm ci, runs a full typecheck (tsc --noEmit), and executes linting.

For deployment, the app is containerized using a multi-stage Dockerfile based on node:20-alpine, keeping the production image lightweight. A docker-compose.yml file is provided to rapidly spin up a local redis:7-alpine container. Production deployment requires specific environment variables, most notably REDIS_URL, MONGO_URI, and GEMINI_API_KEY. Crucially, because it is deployed behind reverse proxies or load balancers (like Render), the Express app explicitly enables app.set('trust proxy', 1) to accurately resolve client IPs and ensure secure cookie handling.

Project Structure

β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app.ts
β”‚   β”œβ”€β”€ server.ts
β”‚   β”œβ”€β”€ config/
β”‚   β”‚   β”œβ”€β”€ database.ts
β”‚   β”‚   β”œβ”€β”€ environment.ts
β”‚   β”‚   β”œβ”€β”€ rateLimitStore.ts
β”‚   β”‚   β”œβ”€β”€ redis.ts
β”‚   β”œβ”€β”€ constants/
β”‚   β”‚   β”œβ”€β”€ aiPrompts.ts
β”‚   β”‚   β”œβ”€β”€ chatMessages.ts
β”‚   β”‚   β”œβ”€β”€ evaluationConstant.ts
β”‚   β”‚   β”œβ”€β”€ streak.ts
β”‚   β”œβ”€β”€ controllers/
β”‚   β”‚   β”œβ”€β”€ activityControllers.ts
β”‚   β”‚   β”œβ”€β”€ aiControllers.ts
β”‚   β”‚   β”œβ”€β”€ authControllers.ts
β”‚   β”‚   β”œβ”€β”€ projectControllers.ts
β”‚   β”‚   β”œβ”€β”€ userControllers.ts
β”‚   β”‚   β”œβ”€β”€ workspaceControllers.ts
β”‚   β”œβ”€β”€ middlewares/
β”‚   β”‚   β”œβ”€β”€ aiValidationMiddleware.ts
β”‚   β”‚   β”œβ”€β”€ authMiddleware.ts
β”‚   β”‚   β”œβ”€β”€ cacheMiddleware.ts
β”‚   β”‚   β”œβ”€β”€ rateLimiters.ts
β”‚   β”‚   β”œβ”€β”€ validationMiddleware.ts
β”‚   β”‚   β”œβ”€β”€ workspaceValidationMiddleware.ts
β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”œβ”€β”€ activityModel.ts
β”‚   β”‚   β”œβ”€β”€ aiChatModel.ts
β”‚   β”‚   β”œβ”€β”€ aiEvaluationModel.ts
β”‚   β”‚   β”œβ”€β”€ projectModel.ts
β”‚   β”‚   β”œβ”€β”€ taskFileModel.ts
β”‚   β”‚   β”œβ”€β”€ taskModel.ts
β”‚   β”‚   β”œβ”€β”€ userFileModel.ts
β”‚   β”‚   β”œβ”€β”€ userModel.ts
β”‚   β”‚   β”œβ”€β”€ userProgressModel.ts
β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   β”œβ”€β”€ activityRoute.ts
β”‚   β”‚   β”œβ”€β”€ aiRoute.ts
β”‚   β”‚   β”œβ”€β”€ authRoute.ts
β”‚   β”‚   β”œβ”€β”€ projectRoute.ts
β”‚   β”‚   β”œβ”€β”€ userRoute.ts
β”‚   β”‚   β”œβ”€β”€ workspaceRoute.ts
β”‚   β”œβ”€β”€ services/
β”‚   β”‚   β”œβ”€β”€ activityService.ts
β”‚   β”‚   β”œβ”€β”€ aiChatService.ts
β”‚   β”‚   β”œβ”€β”€ aiEvaluationService.ts
β”‚   β”‚   β”œβ”€β”€ authService.ts
β”‚   β”‚   β”œβ”€β”€ projectService.ts
β”‚   β”‚   β”œβ”€β”€ userServices.ts
β”‚   β”‚   β”œβ”€β”€ workspaceService.ts
β”‚   β”œβ”€β”€ types/
β”‚   β”‚   β”œβ”€β”€ aiTypes.ts
β”‚   β”‚   β”œβ”€β”€ projectTypes.ts
β”‚   β”‚   β”œβ”€β”€ userTypes.ts
β”‚   β”‚   β”œβ”€β”€ workspaceTypes.ts
β”‚   β”œβ”€β”€ utils/
β”‚   β”‚   β”œβ”€β”€ authUtils.ts
β”‚   β”‚   β”œβ”€β”€ cookieUtils.ts
β”‚   β”‚   β”œβ”€β”€ customErrors.ts
β”‚   β”‚   β”œβ”€β”€ geminiClient.ts
β”‚   β”‚   β”œβ”€β”€ mappers.ts
β”‚   β”‚   β”œβ”€β”€ responseUtils.ts
β”‚   β”‚   β”œβ”€β”€ ...
β”‚   β”œβ”€β”€ scripts/
β”‚   β”‚   β”œβ”€β”€ seedDatabase.ts
β”‚   β”‚   β”œβ”€β”€ seedTypes.ts

Getting Started

Prerequisites

  • Node.js (v20+)
  • MongoDB
  • Redis (Docker recommended)

Installation & Local Dev

# Clone the repository
git clone https://github.com/Duythanducminh/DevFlow-BE.git
cd devflow-be

# Install dependencies
npm ci

# Setup environment variables
cp .env.example .env

### Environment Variables
| Variable | Description | Example |
|----------|-------------|---------|
| `PORT` | The port the server runs on | `3000` |
| `MONGO_URI` | MongoDB connection string | `mongodb://localhost:27017/devflow` |
| `REDIS_URL` | Redis connection string | `redis://localhost:6379` |
| `GEMINI_API_KEY` | Google Generative AI SDK key | `AIza...` |
| `JWT_SECRET` | Secret for signing auth tokens | `your_super_secret_key` |

# Start Redis (using Docker)
docker-compose up -d

# Run the development server
npm run dev

Contributors

devflow-be contributors

License & Feedback

Distributed under the MIT License. If you have feedback or encounter issues, please open an issue in the repository.

Releases

Packages

Contributors

Languages