https://github.com/ForeverHYX/Homepage
Overview
foreverhyx.top is a personal academic homepage built with a decoupled front-end/back-end architecture. The front-end runs on Next.js 16 (React 19), the back-end on FastAPI (Python), and Nginx serves as the reverse proxy that unifies everything behind a single domain. The entire system is deployed on a single server with the back-end managed by systemd.
The core design philosophy is a lightweight CMS powered by Markdown files — all page content (bio, articles, news updates) is stored directly in the filesystem. There is no database; the back-end parses Markdown files and exposes JSON APIs, while the front-end performs server-side rendering (SSR).
System Architecture Overview
Browser
│
▼
┌─────────────────────────────────────────────┐
│ Nginx (SSL Termination) │
│ Port 443 (HTTPS) / Port 80 → 301 Redirect │
│ │
│ /api/* → FastAPI :8000 │
│ /static/* → FastAPI :8000 │
│ /uploads/* → FastAPI :8000 │
│ /_next/* → Static Files (.next/static/) │
│ /* → Next.js :3000 │
└─────────────────────────────────────────────┘
│ │
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ FastAPI │ │ Next.js 16 │
│ :8000 │ │ :3000 │
│ (gunicorn │ │ (standalone) │
│ + uvicorn │ │ │
│ workers) │ │ SSR + CSR │
│ │ │ │
│ content/ │ │ Rewrites → │
│ uploads/ │ │ :8000/api/* │
│ static/ │ │ │
└──────────────┘ └──────────────────┘
Front-end: Next.js 16 + React 19
Technology Stack
| Dependency | Version | Purpose |
|---|---|---|
| Next.js | 16.2.2 | Full-stack React framework |
| React | 19.2.4 | UI rendering |
| TypeScript | ^5 | Type safety |
| highlight.js | 11.9.0 (CDN) | Code block syntax highlighting |
Directory Structure
frontend/
├── app/ # App Router pages
│ ├── layout.tsx # Root layout (theme, fonts, SEO metadata)
│ ├── page.tsx # Home page
│ ├── articles/ # Article list + detail pages
│ │ ├── page.tsx # List page (with tag filtering)
│ │ └── [slug]/page.tsx # Article detail page
│ ├── gallery/page.tsx # Photo gallery
│ ├── resume/page.tsx # Resume page
│ ├── upload/ # File upload management dashboard
│ │ ├── page.tsx
│ │ ├── types.ts
│ │ ├── upload-client.tsx
│ │ └── upload-meta-modal.tsx
│ ├── login/ # Login page
│ ├── api/ # API route proxy
│ └── globals.css # Global styles
├── components/ # UI components
│ ├── site-header.tsx # Navbar (search, theme toggle, mobile menu)
│ ├── site-footer.tsx # Footer
│ ├── home-sidebar.tsx # Home sidebar (profile + news feed)
│ ├── home-legacy-effects.tsx # Visual effects initialization entry
│ ├── home-lightfield.ts # Lightfield animation engine
│ ├── home-liquid-glass.ts # Liquid glass effect engine
│ ├── content-enhancer.tsx # Content enhancer (code highlighting, GitHub cards)
│ ├── gallery-view.tsx # Gallery view
│ ├── resume-view.tsx # Resume view
│ └── icons.tsx # SVG icon set
└── lib/
├── api.ts # Data fetching layer (unstable_cache + fetch)
└── types.ts # TypeScript type definitions
Key Design Decisions
1. output: "standalone"
Next.js is built in standalone mode, producing a self-contained production bundle that does not depend on node_modules, making it suitable for containerized or bare-metal deployment.
2. API Rewrites Proxy
// next.config.ts
async rewrites() {
return [
{ source: "/api/:path*", destination: `${backendOrigin}/api/:path*` },
{ source: "/static/:path*", destination: `${backendOrigin}/static/*` },
{ source: "/uploads/:path*", destination: `${backendOrigin}/uploads/*` },
];
}
The front-end proxies /api/*, /static/*, and /uploads/* requests to the FastAPI back-end via rewrites. In production, Nginx handles these routes directly; the rewrites are primarily used for local development.
3. Server-Side Rendering + Client Hydration
The home page and article listing are Server Components that fetch data and render HTML on the server, ensuring SEO friendliness and fast first-paint. Interactive components (navbar, sidebar, upload manager) are marked with "use client" and hydrate on the client side.
4. Data Caching Strategy
// lib/api.ts
export const getHomePayload = unstable_cache(
async () => requestJson<HomePayload>("/api/site/home"),
["home"],
{ revalidate: 60 } // 60-second revalidation
);
Next.js unstable_cache caches API responses with 60-second automatic revalidation. The Gallery page skips caching to ensure real-time data after file operations.
5. SEO Optimization
The root layout configures comprehensive SEO metadata: - Open Graph tags (Facebook/LinkedIn share previews) - Twitter Card tags - Structured keywords - Canonical URL - Robots indexing directives - Google Fonts preconnect (Playfair Display + Noto Serif SC)
Back-end: FastAPI + Python
Technology Stack
| Dependency | Version | Purpose |
|---|---|---|
| FastAPI | 0.115.8 | Web framework |
| uvicorn | 0.30.6 | ASGI server |
| gunicorn | 23.0.0 | Process manager (multi-worker) |
| Markdown | 3.7 | Markdown → HTML conversion |
| Pillow | - | Image processing (JPG → WebP) |
| bcrypt + passlib | - | Password hashing |
| slowapi | - | API rate limiting |
| python-dotenv | - | Environment variable management |
Directory Structure
app/
├── main.py # FastAPI application entry point
├── config.py # Configuration (paths, rate limiter, env vars)
├── auth.py # Authentication (bcrypt + session tokens)
├── cache.py # mtime-based in-memory cache
├── articles.py # Article parsing and management
├── news.py # News aggregation (manual + articles + gallery)
├── content_utils.py # Content utilities (about parsing, section extraction)
├── markdown_utils.py # Markdown renderer (with PDF embed extension)
├── education.py # Education timeline parser
├── file_utils.py # File handling (image conversion, safe path joining)
├── gallery_utils.py # Gallery management (config file read/write)
├── utils.py # Unified re-exports
└── routers/
├── pages.py # Page data APIs
├── upload.py # File upload APIs
└── auth.py # Login API
API Endpoint Reference
| Endpoint | Method | Description | Auth |
|---|---|---|---|
/api/site/home |
GET | Home page data (about, sections, news) | No |
/api/site/articles |
GET | Article list (tag filtering supported) | No |
/api/site/articles/{slug} |
GET | Article detail (with TOC) | No |
/api/site/gallery |
GET | Gallery data (focus parameter supported) | No |
/api/search-index |
GET | Full-site search index | No |
/api/upload |
POST | File upload | Required |
/api/files |
GET | File listing | Required |
/api/files/{path} |
DELETE | Delete file or folder | Required |
/api/folder |
POST | Create folder | Required |
/api/folder/meta |
POST | Update folder metadata | Required |
/api/gallery/toggle |
POST | Toggle gallery visibility | Required |
/api/login |
POST | Login | No |
Content Management System
Core design: Markdown files as the database.
content/
├── about.md # Personal info (email, GitHub, location, role)
├── content.md # Home page body (split by H1 headings)
├── news.md # Manual news entries
└── articles/ # Articles directory
└── *.md # One Markdown file per article
Article metadata format:
Each article .md file begins with a title heading (# Title), followed by metadata lines for Date, Author, Tags (comma-separated), and Abstract. The parser reads these lines from the top of the file and uses them for listing and filtering.
Caching mechanism: In-memory cache keyed by file modification time (mtime). When a file has not changed, the cached result is returned directly, avoiding redundant Markdown parsing. The cache key is the file's absolute path concatenated with its mtime.
Authentication System
- Passwords are hashed with bcrypt for storage
- On successful login, a
token_urlsafe(32)random session token is generated - Sessions are stored in a JSON file (
.sessions.json), ensuring consistency across multiple workers - Cookies are set with
HttpOnly,Secure(in production), andSameSite=Lax - Session validity: 24 hours, with automatic cleanup of expired entries
secrets.compare_digestis used to prevent timing attacks on username comparison
Security Measures
- Rate limiting: slowapi enforces a global 200 requests/minute cap, with stricter limits on sensitive endpoints (login: 10/min, upload: 30/min)
- Path traversal protection:
safe_join()ensures all file operations stay within the base directory - Upload security: File extension blocklist (
.exe,.php,.html, etc.) and 50 MB size limit - Security headers: Nginx sets
X-Content-Type-Options,X-Frame-Options, andStrict-Transport-Security - Image processing: Uploaded JPGs are automatically converted to WebP (quality 80); images exceeding 1920px are downscaled
Markdown Rendering
The back-end uses the Python-Markdown library with the following extensions:
- fenced_code: fenced code block syntax
- tables: table support
- toc: table of contents generation
- Custom PdfExtension: automatically converts  into an <embed> tag for inline PDF document preview
News Aggregation
news.py merges three data sources into a unified timeline:
1. Manual news entries from news.md
2. New article publications from articles/
3. New gallery album releases
Items are sorted by date in descending order. The sidebar displays the 6 most recent entries, with a modal to view all.
Visual Effects Engines
This is the most distinctive part of the site — two fully custom-built visual effect systems with zero third-party animation library dependencies.
Lightfield Animation
File: home-lightfield.ts (311 lines)
Creates 6 gradient light spots on the page's background layer, forming a dynamic light field effect:
- Each spot has independent animation parameters: position (x, y), size, blur, opacity, scale
- Driven by
requestAnimationFrame, withlerp(linear interpolation) smoothing transitions toward random target values each frame - Spots pick new random target positions every 4–8 seconds
- Mouse parallax: spots shift based on cursor position (different parallax coefficients per spot), creating a sense of depth
- Theme-adaptive: light and dark themes use different color palettes (blues for light mode, purples for dark mode), monitored via
MutationObserveron theme attribute changes - Performance optimizations:
prefers-reduced-motiondetection: renders only a static frame when animations are disabled- Animation loop pauses when the page is hidden (
visibilitychange) - Uses CSS transforms (GPU-accelerated) instead of top/left
- Drives styles via
--spot-*CSS custom properties
Liquid Glass Effect
File: home-liquid-glass.ts (880 lines)
This is the most technically complex implementation in the entire project — using SVG filters to simulate a liquid glass material on web page elements:
How it works:
1. A displacement map is generated using Canvas 2D — based on a signed distance field (SDF) of a rounded rectangle to compute the refraction direction at each pixel
2. At the edges of the map, color channels encode normal direction information (red = X direction, blue = Y direction); the center region remains neutral gray (128, 128)
3. The SVG <feDisplacementMap> filter applies displacement to create edge refraction
4. Different displacement scales are applied to each of the R, G, B channels independently, simulating chromatic aberration
5. A backdrop-filter: blur() saturate() brightness() is layered on top to produce the frosted glass background
Interactivity:
- The glass effect activates when the cursor approaches a card
- Light source position follows the mouse in real time, producing dynamic reflections
- A global ambient light effect is applied to sidebar cards (always active)
- Element size changes are handled via ResizeObserver
Performance strategies:
- Displacement maps are cached by dimensions (Map<string, string>), so cards of the same size share a single map
- requestAnimationFrame batches DOM updates to avoid frequent reflows
- Filter effects are disabled on mobile viewports (≤800px)
- The rAF loop stops automatically once animation values converge on their targets
Content Enhancer
File: content-enhancer.tsx
Enhances rendered Markdown content on the client side:
- Code highlighting: dynamically loads highlight.js and applies syntax highlighting to
<pre><code>blocks - Code block chrome: wraps each code block in a macOS-style title bar with traffic-light dots, language label, collapse and maximize buttons
- GitHub repository cards: automatically detects GitHub repo URLs in text, fetches metadata via the GitHub API, and renders a rich card with description, language, star count, and fork count
- Theme-aware switching: dynamically swaps highlight.js stylesheets between light and dark themes
Deployment Architecture
Process Management
Systemd Service: foreverhyx-homepage.service
├── FastAPI (gunicorn + uvicorn workers)
│ WorkingDirectory: /root/newhomepage
│ Command: gunicorn app.main:app -k uvicorn.workers.UvicornWorker
│ --bind 127.0.0.1:8000 --workers 2 --timeout 60
│ Restart: always (3s delay)
│
└── Next.js (standalone build)
Port: 3000
Nginx Configuration
Nginx serves as the unified entry point and handles:
- SSL termination: Let's Encrypt certificates, TLS 1.2/1.3
- HTTP → HTTPS redirect
- Route dispatching:
/api/*→ FastAPI :8000 (with proxy headers)/static/*→ FastAPI :8000 (7-day cache)/uploads/*→ FastAPI :8000 (7-day cache)/_next/static/*→ direct mapping to.next/static/(1-hour cache)/*→ Next.js :3000 (HTTP/1.1 keep-alive)- Gzip compression: level 5, minimum 256 bytes
- Security headers: HSTS, X-Content-Type-Options, X-Frame-Options
- Upload limit:
client_max_body_size 100M
Environment Variables
HOMEPAGE_CONTENT_DIR=/root/newhomepage/content
HOMEPAGE_UPLOAD_DIR=/root/newhomepage/uploads
HOMEPAGE_COOKIE_SECURE=true
The password hash is configured via HOMEPAGE_UPLOAD_PASS_HASH in the .env file, using the bcrypt algorithm.
Front-end/Back-end Data Flow
Taking the home page as an example:
1. User visits https://foreverhyx.top
2. Nginx proxies the request to Next.js :3000
3. Next.js executes page.tsx (Server Component)
4. getHomePayload() calls FastAPI /api/site/home
5. FastAPI:
a. get_about_info() → parses content/about.md
b. parse_markdown_sections("content.md") → renders HTML split by H1 sections
c. parse_education_timeline() → converts Education section to timeline HTML
d. parse_and_merge_news() → aggregates news from all sources
6. Returns JSON payload
7. Next.js renders HTML and sends it to the browser
8. Browser loads JS:
a. HomeSidebar hydrates (news expand modal)
b. HomeLegacyEffects initializes (lightfield + liquid glass)
c. ContentEnhancer enhances content (code highlighting + GitHub cards)
Theme System
The theme system uses CSS custom properties combined with a data-theme attribute:
- Before the page renders, an inline script reads
localStorageandprefers-color-schemeto setdata-theme - Toggling the theme updates both the
data-themeattribute and thecolorSchemestyle - All colors are defined through CSS variables (
--primary,--text,--surface, etc.) - Visual effect components use
MutationObserverto listen for theme changes and adjust dynamically
Summary
This project is a carefully engineered full-stack personal homepage with several technical highlights:
- Zero-database architecture: Markdown files serve as the sole data source, simplifying deployment and backup
- Custom visual effects: SVG filter-based liquid glass and lightfield animations, built entirely from scratch without third-party libraries
- Decoupled front-end/back-end: FastAPI serves JSON APIs while Next.js handles SSR, with clear separation of concerns
- Security-hardened design: rate limiting, path traversal prevention, upload safety, session management, and enforced HTTPS
- Multi-layer caching: Next.js
unstable_cache+ FastAPI mtime cache, Gzip compression, static asset long-term caching, and GPU-accelerated animations - SEO-friendly: comprehensive metadata, SSR rendering, and Open Graph support
- Production-ready: systemd process management, Nginx reverse proxy, SSL certificates, and structured logging