Anurag.dev
Portfolio
README.md
17.3 KB353 lines1970 wordssynced

#Anurag.dev — Enterprise Personal Portfolio & Autonomous AI Agent

Anurag.dev is a bleeding-edge, full-stack personal brand platform. It transcends traditional static portfolios by integrating a fully autonomous LangChain LLM Agent that serves as a 24/7 personal assistant for visitors. Built on an Express REST API backend with PostgreSQL + Prisma and a highly animated Next.js frontend, this project demonstrates scalability, resilience, and advanced AI integration.

##šŸ—ļø Master System Architecture

Anurag.dev relies on a strictly decoupled architecture, meaning the frontend, backend, database, and AI inference engines can all crash, restart, and scale independently without tearing each other down.

flowchart TB
    subgraph Frontend [Next.js Client Domain]
        subgraph UI [React Layout & Logic]
            Port["Portfolio Views"]
            AgentW["Agent Widget Floating UI"]
            Admin["Admin Dashboard"]
        end
        
        subgraph Hooks [State & API Hooks]
            SessionHook["useAgentSession.ts"]
            Api["Custom API Client"]
        end
        
        CircuitBreaker{"Offline Circuit Breaker"}
    end

    subgraph Backend [Node.js / Express API Domain]
        Router["Express Router /api/v1/"]
        StandardBusiness["Standard CRUD Services"]
        
        subgraph LangChain_Agent [Enterprise LangChain Engine]
            AgentLoop["Manual ReAct Loop"]
            Memory["Persistent Session Memory"]
            Logger["Structured Agent Logger"]
            
            subgraph Models [Dual-LLM with Sticky Fallback]
                HF["Primary: Qwen 2.5 72B"]
                Gemini["Fallback: Gemini 2.5 Flash"]
            end
            
            subgraph MCP_Tools [Model Context Protocols]
                GitHubTool["GitHub Activity + README"]
                LeetCodeTool["LeetCode Stats"]
                PortfolioTool["Portfolio Project Search"]
                ContactTool["Direct DB Lead Insertion"]
            end
        end
    end

    subgraph Persistence [Data Layer]
        Postgres[("PostgreSQL Database")]
        Redis[("Redis Cache")]
    end

    %% Connections
    Port <--> Api
    AgentW <--> SessionHook
    SessionHook <--> Api
    Api <--> CircuitBreaker
    CircuitBreaker <--> Router
    
    Router <--> StandardBusiness
    Router <--> AgentLoop
    
    StandardBusiness <--> Postgres
    StandardBusiness <--> Redis
    
    AgentLoop <--> Memory
    AgentLoop --> Logger
    AgentLoop --> HF
    HF -.-> |Primary fails| Gemini
    
    AgentLoop <--> MCP_Tools
    MCP_Tools <--> Postgres
    MCP_Tools -.-> |External APIs| GitHubTool

##🧠 Deep Dive: The AI Agent Architecture

Instead of basic chatbot text-in/text-out completions, the Anurag.dev agent operates using the Model Context Protocol (MCP) and a manual ReAct (Reasoning and Acting) loop with enterprise-grade failover.

How a Chat Query Works (Step-by-Step)

  1. User Input: A visitor types "What React projects have you built? And how many LeetCode questions have you solved?"
  2. Context Injection (RAG): The backend pulls Anurag's profile data (Bio, Skills, Job Status) from PostgreSQL and injects it into the SystemPersona prompt alongside screen-awareness context (currentUrl).
  3. The LLM Loop Begins: The primary LLM reads the prompt and decides it needs external data. It generates a JSON payload requesting tools: search_projects("React") and get_leetcode_stats().
  4. Tool Execution: The Express backend intercepts these requests and executes them with full observability logging (execution time, output preview, success/failure status).
  5. Final Generation: Tool outputs are fed back into the LLM for a second pass. The model structures a human-readable Markdown response and returns it to the React UI.

The Dual-LLM Architecture with Sticky Fallback

The system operates on a dual-engine core (src/modules/agent/core/llm.factory.ts):

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│              LLM Invocation Flow                     │
│                                                      │
│  Request Loop 1:                                     │
│    ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”     ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”      │
│    │ HuggingFace │────►│ Success? → Continue  │      │
│    │  (Primary)  │     │ Fail? → Set STICKY   │      │
│    ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜     │   flag, try Gemini   │      │
│                        ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜      │
│                                                      │
│  Request Loops 2-4:                                  │
│    ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”      │
│    │ STICKY flag set? → Skip Primary entirely │      │
│    │ Go directly to Gemini (no timeout wait)  │      │
│    ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜      │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Key design decisions:

  • HuggingFace (Qwen 2.5 72B-Instruct) is the primary LLM — fast, reliable, no rate-limit issues on free-tier.
  • Google Gemini 2.5 Flash is the fallback — powerful but subject to daily free-tier rate limits.
  • Sticky Fallback: Once the primary fails within a single request, all subsequent LLM loops in that request skip the primary entirely. This eliminates repeated 30-second timeout penalties.
  • 30-Second Timeout: Every LLM invocation is wrapped in a Promise.race() timeout to prevent SDK-level internal retry hangs (Google's SDK retries internally for ~3 minutes by default).

MCP Tool Registry

ToolDescriptionExternal API
get_github_activityFetches GitHub profile stats and recent 5 eventsapi.github.com
read_github_readmeReads raw README.md from any public repositoryapi.github.com
get_leetcode_statsFetches LeetCode solving stats and rankingalfa-leetcode-api.onrender.com
search_projectsSearches published portfolio projects by keywordPostgreSQL (Prisma)
submit_contact_leadInserts a contact lead directly into the databasePostgreSQL (Prisma)

Autonomous Navigation

The Agent can trigger client-side routing via [NAVIGATE:/path] tokens embedded in its response. The frontend's useAgentSession hook intercepts these tokens, executes router.push(), and strips the command from the visible message — so the user sees a seamless page transition.

##šŸ“Š Structured Observability Logging

The Agent pipeline includes a centralized logging system (agent.logger.ts) that provides full visibility into every layer:

[2026-03-26 01:58:22] [INFO]  [Agent:SYSTEM] ━━━ New Request ━━━
                              {"sessionId":"abc","llmMode":"dual","primary":"HuggingFace","fallback":"Gemini"}
[2026-03-26 01:58:23] [INFO]  [Agent:LLM]    🧠 Invoking HuggingFace (Qwen2.5-72B-Instruct)
[2026-03-26 01:58:27] [INFO]  [Agent:LLM]    āœ… LLM responded {"durationMs":4600,"hasToolCalls":true}
[2026-03-26 01:58:27] [INFO]  [Agent:TOOL]   ⚔ Executing: get_github_activity
[2026-03-26 01:58:28] [INFO]  [Agent:TOOL]   āœ… get_github_activity completed {"durationMs":875}

[2026-03-26 01:58:52] [INFO]  [Agent:SYSTEM] ━━━ Request Complete ━━━
                              {"usedProvider":"HuggingFace","totalDurationMs":30200,"llmLoops":2}

Log Categories: SYSTEM, LLM, TOOL, MEMORY, CTRL
Log Levels: INFO, WARN, ERROR, DEBUG (DEBUG only in development)

##šŸ›”ļø Error Handling Strategy

Anurag.dev implements a zero-crash error handling philosophy. The AI Agent is designed to never return an HTTP 500 to the frontend.

Backend Error Cascade

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  Tool Execution Error (e.g., GitHub API down)      │
│  → Caught inside tool → Returns error string       │
│  → LLM reads error → Generates human-friendly msg  │
│  → User sees: "I can't fetch GitHub right now..."   │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  LLM Invocation Error (e.g., API rate limit)       │
│  → Primary fails → Sticky flag set                 │
│  → Fallback LLM invoked → Success                  │
│  → User doesn't notice anything                    │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│  Both LLMs Fail (catastrophic)                     │
│  → Controller catches → Returns HTTP 200           │
│  → reply: "I ran into a hiccup..."                 │
│  → Error category logged: RATE_LIMIT / TIMEOUT /   │
│    NETWORK / INTERNAL                              │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

Frontend Error Isolation

LayerStrategy
useAgentSession hookAll API errors caught → displayed as a chat bubble. Error never propagates to React tree.
ApiClientError handlingReads .message directly (not Axios-style .response.data). Fallback message for network errors.
Global error.tsx boundaryStyled terminal-themed error page with stack trace toggle (dev only) and recovery button. Only triggers for non-Agent rendering crashes.
Circuit BreakerAfter 3 consecutive API failures, portfolio falls back to static JSON. Background health checks resume live API after recovery.

##šŸ›”ļø Frontend Hybrid Strategy (Circuit Breaker)

To guarantee 100% uptime regardless of backend maintenance windows, the frontend wraps API calls in a Circuit Breaker state machine:

  1. Online (Closed): The Next.js app queries the Express API normally.
  2. Tripped (Open): After 3 consecutive HTTP timeouts or 500 errors, the frontend "trips" its breaker.
  3. Offline Mode: The application seamlessly falls back to reading static JSON files (client/src/api/fallback/) containing last-known-good data.
  4. Recovery (Half-Open): A background job pings the backend health route every 60 seconds. Once healthy, the breaker closes and live API requests resume.

The visitor never sees a white error screen.

##šŸ’» Technical Stack

LayerTechnology
FrontendNext.js 16, React 19, Tailwind CSS v4, Framer Motion
BackendExpress, TypeScript, Prisma ORM, Zod validation
DatabasePostgreSQL 14+
CacheRedis 6+
AI PrimaryHuggingFace Inference API (Qwen 2.5 72B-Instruct) via @langchain/openai
AI FallbackGoogle Gemini 2.5 Flash via @langchain/google-genai
AuthJWT (access + refresh tokens), bcrypt, account lockout
MediaCloudinary (image/file uploads via Multer)
ObservabilityCustom structured logger with timestamped categories

##āš™ļø Environment Variables

Backend (server/.env)

VariableRequiredDescription
NODE_ENVāœ“development or production
PORTāœ“Backend port (default: 4000)
DATABASE_URLāœ“PostgreSQL connection string
REDIS_HOST / REDIS_PORTā—‹Redis instance for route caching
JWT_SECRETāœ“64-char symmetric key for access tokens
JWT_REFRESH_SECRETāœ“Symmetric key for refresh tokens
CLOUDINARY_CLOUD_NAMEāœ“Cloudinary cloud name
CLOUDINARY_API_KEYāœ“Cloudinary API key
CLOUDINARY_API_SECRETāœ“Cloudinary API secret
HF_TOKENāœ“HuggingFace access token (primary LLM)
GEMINI_API_KEYā—‹Google Gemini API key (fallback LLM)
AI_PROVIDERā—‹Force-select provider (legacy, defaults to gemini)
GITHUB_TOKENā—‹GitHub PAT for elevated API rate limits

Frontend (client/.env.local)

VariableRequiredDescription
NEXT_PUBLIC_API_URLāœ“Backend URL (e.g., http://localhost:4000)
NEXT_PUBLIC_API_TIMEOUT_MSā—‹API timeout in ms (default 5000; mobile uses a higher floor)

For production deployments, set NEXT_PUBLIC_API_URL to a publicly reachable HTTPS backend URL (not localhost).

##šŸš€ Quick Start

# 1. Backend
cd server
npm install
cp .env.example .env        # Fill in all variables
npm run db:generate          # Generate Prisma types
npm run db:migrate           # Push schema to PostgreSQL
npm run db:seed              # Seed initial data + admin account
npm run dev                  # → http://localhost:4000

# 2. Frontend
cd ../client
npm install
cp .env.local.example .env.local
npm run dev                  # → http://localhost:3000

Default Admin: admin / admin123

##šŸ“¦ File System Structure

personal_portfolio/
ā”œā”€ā”€ server/                          # Node.js + Express + Prisma
│   ā”œā”€ā”€ prisma/                      # Schema, migrations, seed
│   └── src/
│       ā”œā”€ā”€ controllers/             # Standard HTTP handlers
│       ā”œā”€ā”€ services/                # Business logic (DB, external APIs)
│       ā”œā”€ā”€ routes/                  # Express routing + API docs
│       ā”œā”€ā”€ schemas/                 # Zod validation schemas
│       ā”œā”€ā”€ middleware/              # Auth, validation, rate limiting
│       ā”œā”€ā”€ config/                  # Environment & app config
│       ā”œā”€ā”€ utils/                   # ApiError, ApiResponse helpers
│       └── modules/
│           └── agent/               # [STANDALONE] AI Agent Engine
│               ā”œā”€ā”€ agent.service.ts     # ReAct loop with sticky fallback
│               ā”œā”€ā”€ agent.controller.ts  # Zero-crash error handling
│               ā”œā”€ā”€ agent.admin.*        # Admin CRUD for sessions
│               ā”œā”€ā”€ core/
│               │   ā”œā”€ā”€ llm.factory.ts   # Dual-LLM singleton init
│               │   ā”œā”€ā”€ agent.logger.ts  # Structured observability
│               │   ā”œā”€ā”€ memory.service.ts# Persistent Prisma sessions
│               │   └── prompts.ts       # System persona
│               ā”œā”€ā”€ tools/               # MCP tool implementations
│               │   ā”œā”€ā”€ github.tool.ts   # GitHub activity + events
│               │   ā”œā”€ā”€ github.repo.tool.ts # README reader
│               │   ā”œā”€ā”€ leetcode.tool.ts # LeetCode stats
│               │   ā”œā”€ā”€ portfolio.tool.ts# Project search
│               │   └── contact.tool.ts  # Lead insertion
│               └── rag/                 # Context retrieval
│
└── client/                          # React + Next.js App Router
    └── src/
        ā”œā”€ā”€ app/                     # Portfolio, Admin, Resume, README
        ā”œā”€ā”€ modules/                 # Feature modules (profile, projects, blog...)
        │   └── agent/               # AI Widget UI
        │       ā”œā”€ā”€ components/      # Chat window, bubbles, loader
        │       ā”œā”€ā”€ hooks/           # useAgentSession (error isolation)
        │       └── types/           # Message interfaces
        ā”œā”€ā”€ layout/                  # App shell (sidebar, scroll, TOC)
        ā”œā”€ā”€ api/                     # API client + circuit breaker + fallback
        ā”œā”€ā”€ lib/                     # Skill icons, routes, utils
        └── boot/                    # Splash animation

##šŸ›”ļø Production Security

  • Session Isolation: Conversation history is keyed to randomized browser sessionIds — users cannot read or poison other sessions.
  • Input Sanitization: All user inputs pass through sanitize-html before database insertion.
  • DDoS Protection: express-rate-limit restricts Agent chat to 15 messages/minute per IP.
  • JWT Rotation: 15-minute access tokens with rotated refresh tokens. Account lockout after 3 failed attempts.
  • CORS: Strict origin allowlisting in production.

##šŸ“” API Documentation

Access full API documentation at GET /api/v1/docs.
Live AI Agent architecture status at GET /api/v1/docs/agent.

Author

Designed and Architected by Anurag Basuri

##License

This project is licensed under the MIT License - see the LICENSE file for details.

On this page

Anurag.dev — Enterprise Personal Portfolio & Autonomous AI Agentā”œšŸ—ļø Master System Architectureā”œšŸ§  Deep Dive: The AI Agent Architectureā””How a Chat Query Works (Step-by-Step)ā””The Dual-LLM Architecture with Sticky Fallbackā””MCP Tool Registryā””Autonomous Navigationā”œšŸ“Š Structured Observability Loggingā”œšŸ›”ļø Error Handling Strategyā””Backend Error Cascadeā””Frontend Error Isolationā”œšŸ›”ļø Frontend Hybrid Strategy (Circuit Breaker)ā”œšŸ’» Technical Stackā”œāš™ļø Environment Variablesā””Backend (server/.env)ā””Frontend (client/.env.local)ā”œšŸš€ Quick Startā”œšŸ“¦ File System Structureā”œšŸ›”ļø Production Securityā”œšŸ“” API Documentationā””Authorā”œLicense
ā—UTF-8│Markdown
Last sync: 01:46 AM