Projects


Classic

Three-service microservices system that parses course syllabi using LLMs to extract instructors, meeting times, exam dates, assignments, and grade weights into a unified student dashboard. Eliminates manual cross-referencing across LMS platforms and exports directly to calendar formats.

Local-First LLM Development: Defaults to a local Ollama instance (gemma4:12b) for fully offline development without incurring API costs; Anthropic Claude and Google Gemini are drop-in alternatives configured via a single environment variable, requiring no code changes to switch providers.

Structured Extraction Pipeline: Engineered a strict JSON extraction prompt — no markdown fences, enforced null semantics, percentage-to-decimal conversion — parsing syllabi into typed Go structs covering instructors (name, email, office hours), meeting times, exam dates, assignments, projects, and grade weights.

Testing Infrastructure: Validated parser correctness with unit tests that mock LLM provider calls and assert against known syllabus inputs; Playwright component tests render the Next.js frontend in a real browser — both suites run with zero external service dependencies.

BlueBot

Discord bot platform for a Realm of the Mad God gaming community, managing 10k+ members across multiple synchronized servers. Provides automated moderation, OCR-based screenshot parsing, raid management, and real-time cross-guild role synchronization.

Cross-Guild Synchronization: Designed dual-server member synchronization that mirrors nickname changes and affiliate staff role assignments across two connected Discord guilds in real time, with per-guild JSON config files and Bottleneck for API rate limiting.

Database Optimization: Optimized MySQL query performance under high concurrency by implementing primary indexing on user IDs, enabling fast lookups of historical activity logs and punishment records across 10k+ member records.

Containerized Deployment: Decoupled the core bot process from persistent storage by containerizing the bot in Docker while hosting the MySQL database independently on AWS, allowing each component to scale and restart independently.

Pavilion

Full-stack platform for organizing skill-matched badminton sessions — venue discovery, peer-based skill ratings, and session-scoped group coordination. Built as a modular monolith across seven domain-bounded services (user, venue, session, rating, admin, messaging, marketplace) backed by a 17-table PostgreSQL/PostGIS schema.

Peer-Vote Rating Engine: Designed a weighted scoring algorithm that updates a player's skill rating per peer vote — combining pro-rater weighting, calibration-distance decay, and recency-adjusted familiarity discounting so repeated pairings with the same players carry diminishing influence over time — capped so a single high-grade rater's vote can corroborate but never unilaterally manufacture a rating increase.

Tier-Boundary Protection: Implemented asymmetric grade-boundary clamping that pins a player's raw score at the current tier the instant a vote would cross a whole-number grade line, releasing it only after a sustained multi-day trend (7-day demotion window, 3-day promotion window) — preventing rating flicker while still allowing genuine skill movement to register.

Atomic Concurrency Control: Replaced racy read-then-write logic for session capacity, waitlist promotion, and reliability-score deductions with atomic PostgreSQL SECURITY DEFINER functions callable only by the service role, closing overbooking and double-promotion races confirmed against real concurrent-request integration tests.

Domain-Bounded Architecture: Structured the codebase as a modular monolith — npm workspaces splitting a Next.js client, Hono API, and shared @pavilion/types package across seven strictly-bounded domains with no cross-domain imports — so the deferred marketplace domain can later extract into its own service without reworking core logic.

UMBC OISS Data Tool

Full-stack visa case management dashboard for UMBC's Office of International Student Services. Ingests Excel spreadsheets of employee visa records, normalizes and aggregates data across F-1, J-1, H-1B, and PR categories, and surfaces renewal deadlines, pending cases, and period cohort analytics.

Analytics Dashboard: Designed a five-view dashboard covering visa type counts (F-1, J-1, H-1B, PR), year-over-year case trends, upcoming renewal deadlines, a pending applications table, and an individual employee detail view — with period cohort classification mapping visa start dates against academic, reporting, and calendar year boundaries for compliance reporting.

In-Memory State Architecture: Maintained application state as two in-memory Pandas DataFrames (full dataset and filtered active visas) with HTTP-only session cookies scoped per upload and a dedicated logout endpoint that resets both DataFrames, ensuring no visa data persists between user sessions.

This website!

Responsive portfolio site built with Next.js 16 and TypeScript, statically exported and deployed to GitHub Pages via a GitHub Actions CI/CD pipeline that publishes the built output to an external repository on every push to main.

Static Export & CI/CD: Configured Next.js with output: 'export' to generate a fully static site with no server runtime. A GitHub Actions workflow builds and deploys the output directory to an external GitHub Pages repository (chujiaguo.github.io) on every push to main using a scoped personal token.

Content Architecture: Centralized all copy — landing text, experience entries, project descriptions, skills, and coursework — in a single strings.ts module, keeping the component tree purely presentational and making content updates a single-file change.

Hash-Based Deep Linking: Built URL hash deep linking on the Projects page — experience entries on the Resume page link to /projects#<id>, which highlights the matching project card on load and on hashchange events, with the hash cleared on any page click.

Particle Background: Implemented a fixed full-screen particle background using @tsparticles/react (80 linked dots, 120fps cap) rendered behind all page content via a negative z-index fixed layer, with Tailwind responsive breakpoints for mobile and desktop layouts throughout.