Skip to main content

05 / WORK / CASE STUDY

NKUST Alumni Association Platform

The official alumni site — member directory, alumni companies and job board. In development since 2024, now running on the university domain.

TYPE
FULL STACK
SCOPE
In production · full stack + ops
STACK
DJANGO · DRF · MYSQL · REDIS · REACT
LINKS
LIVE

01 / PROBLEM

The alumni association had no unified platform: rosters, partner companies, job posts and announcements were scattered and manually maintained. This system folds 'alumni self-service → admin review → public display' and company self-service job/product listings into one platform, plus public pages for distinguished alumni and the department.

02 / CONSTRAINTS

  • Public on a university domain, holding alumni PII under data-protection law — security expectations are high.
  • Single-server deployment (nginx + gunicorn), no orchestration; ops, security and UX audits all fall on one person.
  • The frontend is CRA (no SSR), yet an alumni site must be indexable by search engines.

03 / ARCHITECTURE

A Django 5 + DRF monolith (11 business apps, 39 models, 38 resource routes plus 118 custom actions) with a React 18 SPA. Authorization is deny-by-default — IsAuthenticated globally, public endpoints explicitly opted in; JWT rides in HttpOnly cookies; Redis caches hot queries.

A custom monitoring subsystem: middleware writes requests, errors and performance metrics into seven models, GeoIP tags origin countries, anomalies alert by email; logs rotate daily with gzip and a one-year retention — recording continuously since May 2025.

04 / RESPONSIBILITIES

Independent full-stack development and operations since 2024/08 (169 commits across both repos): data models, APIs, security hardening, the React frontend, deployment and monitoring.

05 / CHALLENGES → SOLUTIONS

CHALLENGE

A pre-launch security review surfaced serious flaws: privilege escalation via the registration API, serializer mass assignment, and member PII enumerable through sequential IDs.

SOLUTION

The root cause was global AllowAny with per-endpoint locking. Authorization was flipped to deny-by-default and a numbered program (SEC-001–030) fixed items one by one — field whitelists, owner filtering, sensitive-field redaction, uniform responses against enumeration. 29 fixes landed, backed by privilege/IDOR regression tests (7/7 passing).

CHALLENGE

A CRA SPA is hostile to crawlers by default, and off-the-shelf prerenderers shipped a puppeteer too old to use.

SOLUTION

Wrote a custom prerender script (puppeteer + Chrome for Testing): after build it renders 14 public routes back to static HTML, wired into postbuild; the backend serves a dynamic sitemap — fixing, along the way, a field bug that had it returning 500s.

CHALLENGE

No budget for an APM, yet a public site needs to know who is hitting it and what is slowing down.

SOLUTION

Built it in: middleware logs requests/errors/perf, GeoIP tags origins, scoped throttling (login 10/min, registration 10/hr) blocks abuse. The daily-rotated logs accumulating since May 2025 are direct evidence of real operation.

06 / SYSTEM FACTS

11

business apps

100+

API endpoints

30

audit findings (29 fixed)

43

Playwright E2E specs

07 / LESSONS

Start from default-deny. Global AllowAny with per-endpoint locking opened a whole attack surface — remediating before launch cost far more than doing it right from the start.

CRA plus a hand-rolled prerenderer works, but it is fragile — routes are maintained by hand and pinned to a Chrome build. Next time I would pick a framework with native SSR/SSG and delete the whole pipeline.

08 / SCREENS

All screens below show demo (mock) data — no real user data.

Alumni platform home: hero carousel, search bar and latest news
Home (carousel and news)
Alumni company search: keyword search, industry filters and company cards
Company search (filters and sorting)
Alumni job board: table and card views of postings
Job board (table/card views)

NEXT

NKUST Equipment Borrowing System