← Back to Articles

Homepage Technical Architecture Deep Dive

2026-06-02 OpenCode 2227 words · 11 min read
Next.jsFastAPIHomepageWeb Development

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), and SameSite=Lax
  • Session validity: 24 hours, with automatic cleanup of expired entries
  • secrets.compare_digest is 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, and Strict-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 ![alt](file.pdf) 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, with lerp (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 MutationObserver on theme attribute changes
  • Performance optimizations:
  • prefers-reduced-motion detection: 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:

  1. Code highlighting: dynamically loads highlight.js and applies syntax highlighting to <pre><code> blocks
  2. Code block chrome: wraps each code block in a macOS-style title bar with traffic-light dots, language label, collapse and maximize buttons
  3. 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
  4. 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:

  1. SSL termination: Let's Encrypt certificates, TLS 1.2/1.3
  2. HTTP → HTTPS redirect
  3. Route dispatching:
  4. /api/* → FastAPI :8000 (with proxy headers)
  5. /static/* → FastAPI :8000 (7-day cache)
  6. /uploads/* → FastAPI :8000 (7-day cache)
  7. /_next/static/* → direct mapping to .next/static/ (1-hour cache)
  8. /* → Next.js :3000 (HTTP/1.1 keep-alive)
  9. Gzip compression: level 5, minimum 256 bytes
  10. Security headers: HSTS, X-Content-Type-Options, X-Frame-Options
  11. 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:

  1. Before the page renders, an inline script reads localStorage and prefers-color-scheme to set data-theme
  2. Toggling the theme updates both the data-theme attribute and the colorScheme style
  3. All colors are defined through CSS variables (--primary, --text, --surface, etc.)
  4. Visual effect components use MutationObserver to 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