About This Website

This site, originally known as "Jacky's Digital Garden (JDG) ", is my personal AI-powered platform that combines a public facing chatbot with an authenticated multi-agent workflow and flexible RAG reindexing dashboard in the backend.
It is built as a Next.js 15 App Router application with a Retrieval-Augmented Generation (RAG) pipeline that indexes my personal knowledge — an Obsidian-based notes and blog content — to answer questions about my experience and expertise.


System Architecture Overview

The architecture follows a layered pattern, with a React frontend talking to Next.js API routes (the BFF layer), which in turn integrate with external AI services, a vector database, and a separate Python workflow engine.

┌─────────────────────────────────────────────────────────┐
│                    Chatbot Interface                    │
│  React 19 · SSE Streaming · Markdown · Tailwind CSS v4  │
└─────────────────────┬───────────────────────────────────┘
                      │  POST /api/chat
                      ▼
 ┌─────────────────────────────────────────────────────────┐
 │                Middle Layer (BFF + LLM)                 │
 │  Rate Limiter · Injection Filter · LLM API Proxy        │
 └──────────┬──────────────────────────┬───────────────────┘
            │                          │
            ▼                        ▼
┌─────────────────────┐    ┌─────────────────────────────────┐
│   RAG Pipeline      │    │   Other Backend Components      │
│  · Chunker          │    │  · PostgreSQL (app data)        │
│  · Voyage AI Embed  │    │  · iron-session Auth            │
│  · SQLite Vec Store │    │  · Worker Manager (Python)      │
│  · MMR Retriever    │    │  · Audit Logging                │
└─────────────────────┘    └─────────────────────────────────┘

1. Chatbot Interface

Conversation Drawer Screenshot
The chatbot interface with chat history drawer

The public-facing chatbot lives on the homepage and is the primary way visitors interact with the site. It is a client-side React component that manages:

  • SSE Streaming — Messages are streamed from the server via Server-Sent Events, providing real-time token-by-token output with a typing indicator.
  • Markdown Rendering — Assistant responses support full GitHub-Flavored Markdown with syntax highlighting via react-markdown, remark-gfm, and rehype-highlight.
  • Session Management — Each chat session gets a unique ID, enabling conversation history, context windows, and token usage tracking.
  • Citation Display — When the RAG pipeline provides source chunks, citations are surfaced inline so users can see where answers come from.
  • Conversation Drawer — A slide-out panel lets users browse and switch between past conversations, or start fresh ones.

2. Middle Layer — BFF & LLM Proxy

The POST /api/chat route acts as a Backend-for-Frontend (BFF), handling all chat requests before they reach the LLM:

Request Processing Pipeline

  1. IP Hashing — Client IPs are SHA-256 hashed for privacy-preserving rate limiting.
  2. Rate Limiting — An in-memory sliding-window rate limiter enforces per-minute and per-day caps, returning 429 Too Many Requests with a Retry-After header when exceeded.
  3. Injection Filtering — 10 regex patterns detect and block common prompt injection attempts (role-play override, delimiter injection, encoding tricks, etc.).
  4. Input Validation — Message length is capped at 500 characters; body size is limited to prevent abuse.

RAG Context Assembly & LLM Call

Test Chat Screenshot
A test chat session showing streaming response after RAG reindexing

Before forwarding to the LLM, the route assembles context:

  • Query Embedding — The user's latest message is embedded via Voyage AI.
  • Vector Search — A KNN cosine-similarity search against the SQLite vector store retrieves the top-N relevant chunks.
  • MMR Deduplication — Maximal Marginal Relevance balances similarity against source diversity, preventing one document from dominating results.
  • System Prompt Assembly — Retrieved chunks are combined with persona rules, a grounding instruction, and recent conversation history into the system prompt.
  • LLM Proxy — The assembled messages are forwarded to the DeepSeek API (deepseek-chat) and the SSE response is streamed back to the client.

Graceful Fallback

If the RAG pipeline is unavailable — Voyage API down, index corrupt, or embedding failure — the system transparently falls back to a legacy prompt-stuffing approach with zero user-visible errors (per FR-010).


3. RAG Pipeline

Rebuild Screenshot
RAG reindexing dashboard for flexible knowledge source management

The Retrieval-Augmented Generation pipeline is the core intelligence layer that makes the chatbot knowledgeable about Jacky's experience. It replaces the old approach of dumping the entire knowledge base into every system prompt. Components include:

ModuleFileRole
Chunkersrc/lib/rag/chunker.tsSplits markdown documents on H2 boundaries (min 50, soft max 1500 chars), with recursive character fallback for flat text and HTML-to-text conversion for blog content.
Embeddersrc/lib/rag/embedder.tsVoyage AI client (voyage-4-lite, 1024-dim) with batch processing (64/batch), exponential backoff retry, and input_type support.
Vector Storesrc/lib/rag/vector-store.tsSQLite via better-sqlite3 — BLOB embedding storage, brute-force cosine similarity search (sub-50ms for ~500 chunks), WAL mode, prepared statements.
Retrieversrc/lib/rag/retriever.tsMMR deduplication with source-file-aware heuristic, balancing relevance against content diversity.
Context Buildersrc/lib/rag/context-builder.tsAssembles final system prompt with persona rules, grounding rule, retrieved chunks, and conversation history.

Chunks Screenshot
Dashboard view of chunked knowledge sources with embedding status

Knowledge Sources

  • Obsidian Notes — Markdown files from the obsidian/ directory, recursively loaded at startup.
  • Blog Content — Fetched from a configurable blog URL at startup and converted from HTML to text.

Index Lifecycle

  • Startup — Index is built automatically when the server starts via Next.js instrumentation.
  • Incremental Rebuild — Detects dimension mismatches and rebuilds only when the embedding model changes.
  • Admin Rebuild — Authenticated dashboard users can trigger a manual re-index via the RAG Evaluation dashboard.

4. Other Backend Components

PostgreSQL Database

Application data is stored in PostgreSQL via the postgres.js client (tagged-template SQL, no ORM). Tables include:

  • users — Dashboard user accounts with bcrypt-hashed passwords.
  • registration_requests — Pending account registration requests with review workflow.
  • audit_logs — Immutable audit trail for sensitive actions.
  • pgmigrations — Tracks applied SQL migrations (auto- applied at startup).

Authentication

Session-based auth using iron-session (AES-256-GCM encrypted cookies). Route protection is enforced at two levels:

  • Middleware (src/middleware.ts) — Lightweight cookie check at the edge for all /dashboard/* routes.
  • API Middleware (src/lib/auth/middleware.ts) — Fine-grained requireAuth and requireAdmin guards for API routes.

Login is protected by IP-based rate limiting and account lockout after repeated failures. Passwords are hashed with bcrypt (12 salt rounds).

Workflow Engine

Multi-agent workflows (spec → clarify → plan → tasks → implement → review) are powered by a separate Python/FastAPI service using LangGraph for state-machine orchestration. The Next.js app proxies dashboard requests to this worker over HTTP. Worker health is monitored every 30 seconds.

Email Notifications

Registration requests trigger email notifications via nodemailer with configurable SMTP settings, alerting admins to review new account requests.

Security & Logging

  • CSP Headers — Strict Content-Security-Policy with default-src 'self', WASM support for the tokenizer, and inline scripts for dev tools.
  • X-Frame-Options: DENY — Prevents clickjacking.
  • Structured Logging — JSON-formatted logs to stdout with configurable log level via LOG_LEVEL.
  • Injection Filter — 10 regex patterns guard against prompt injection attacks on the public chatbot.

Tech Stack Summary

LayerTechnology
FrontendNext.js 15.5, React 19, Tailwind CSS v4, TypeScript
BFF / APINext.js API Routes, Server-Sent Events
LLMDeepSeek API (deepseek-chat)
EmbeddingsVoyage AI (voyage-4-lite, 1024-dim)
Vector StoreSQLite (better-sqlite3) — brute-force cosine similarity
Application DBPostgreSQL (postgres.js)
Authiron-session (AES-256-GCM), bcrypt (12 rounds)
Workflow EnginePython FastAPI + LangGraph (separate service)
Emailnodemailer (SMTP)
DeploymentDocker multi-stage build, Dokploy PaaS