Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/HNU-himematsu/HNU-TimeLetter/llms.txt

Use this file to discover all available pages before exploring further.

HNU-TimeLetter (与她的海大时光笺) is an interactive visual narrative website that weaves galgame-style anime characters together with real campus locations at Hainan University (HNU). Visitors move through a scrapbook-meets-private-letter aesthetic — a warm grey paper backdrop, wax-seal red accents, and hand-picked typography — to discover the decisive moments and hidden stories embedded in campus landmarks. Content is authored entirely inside Feishu (Lark) Bitable and delivered to the frontend through a synchronisation pipeline that writes typed JSON artifacts, so editorial teams never touch a line of code.

What Is HNU-TimeLetter?

The project combines three ideas into one cohesive experience:
  • Galgame visual language — illustrated characters, cinematic scene compositions, and deliberate motion design borrowed from Japanese visual-novel games.
  • Campus documentary — real Hainan University locations serve as the stage. Every story is anchored to a map pin, a photograph, and a prose narrative recorded in Feishu Bitable.
  • Community creativity — a public Creation Board lets community members (群友) share their own galgame-inspired ideas in a sticky-note waterfall layout.
The site is deliberately framed as a personal letter: a 5 px white border and 16 px rounded corners wrap the entire viewport, evoking a photograph pulled from a private album, and every page transition reinforces that sense of opening a treasured keepsake.

Application Routes

The site is composed of four routes, each delivering a distinct interaction mode:
RoutePurpose
/Envelope ritual — the opening screen animates an envelope unsealing, then scrolls through About the Project, About Us, Credits, and the Footer as a sequence of full-viewport sections driven by Lenis smooth scroll.
/mapInteractive campus map — on desktop, an SVG map hosts clickable pins that open story cards; on mobile, the same content renders as a vertically scrolling stamp-collection waterfall.
/creationCommunity creation board — a sticky-note masonry grid of ideas submitted by community members, sourced from a dedicated Feishu table.
/adminAdmin panel — a password-protected back-office for triggering manual Feishu syncs, inspecting sync logs, and configuring scheduled tasks.

Technology Stack

Every layer of the stack was chosen to support fluid motion, type safety, and a zero-friction CMS workflow.
LayerTechnologyVersion
FrameworkNext.js App Router + Turbopack16.2.4
LanguageTypeScript (Strict Mode)5+
StylingTailwind CSS v4 + Radix UI / Shadcn-style componentsv4
AnimationFramer Motion — opening screen, transitions, card effects, magnetic buttons, sticky cursorv12
Smooth ScrollLenis — desktop scroll sections with built-in footer snap1.3.x
Scroll Animation@waaark/luge — scroll-driven progressive effects (smooth scroll plugin disabled to decouple from Lenis)0.6.x
State ManagementZustandv5
CMSFeishu Bitable (飞书多维表格)
Object StorageAliyun OSS
Scheduled Tasksnode-schedule — auto-sync from /admin2.1.x
E2E TestingPlaywright
ReactReact 1919.2.3

Key Features

Envelope Opening Ritual

The homepage opens with a full-screen envelope animation powered by Framer Motion. After the seal breaks, Lenis smooth-scroll drives users through a curated sequence of full-viewport story sections — About the Project, About Us, Credits, and Footer — each snapping cleanly into place.

Interactive Campus Map

The /map route renders an interactive campus map on desktop with clickable location pins linked to illustrated story cards. On mobile the identical data renders as a vertical stamp-collection waterfall, ensuring the full story catalogue is accessible on any device without a separate codebase.

Community Creation Board

The /creation route surfaces community-submitted galgame ideas from Feishu as a masonry sticky-note layout. A dedicated Bitable table (FEISHU_CREATION_TABLE_ID) and optional header table (FEISHU_CREATION_HEADER_TABLE_ID) power the board, and content refreshes automatically without a redeploy.

Feishu CMS Integration

Feishu Bitable is the single source of truth for all content. The npm run sync command (which wraps src/scripts/sync-feishu.ts) pulls records, uploads image attachments to Aliyun OSS, and writes three typed JSON files into src/data/. The admin panel exposes a manual sync trigger and a scheduled-task configurator for production environments.

Zero-Config Content API

Runtime API routes under src/app/api/ serve the pre-written JSON files with no-store cache headers, giving the frontend live data without a database query. The client polls these endpoints on a configurable interval, so new content from a Feishu sync appears on-screen without a page reload.

Dual Deployment Model

The project supports Vercel Preview deployments (using committed JSON as build-time fallback data) and self-hosted production environments where GitHub Actions executes the full quality gate → sync → build → deploy pipeline on the release branch. Both models share the same codebase and content API surface.

Data Flow Overview

Content travels from Feishu to the browser in three clearly separated stages:
Feishu Bitable (single source of truth)

        │  npm run sync  (src/scripts/sync-feishu.ts)
        │  • Fetches records via Feishu Open API
        │  • Downloads image attachments
        │  • Uploads images to Aliyun OSS, writes back public URLs
        │  • Writes typed JSON to src/data/

src/data/
  ├── content.json          ← homepage stories
  ├── creation-board.json   ← community creation board
  └── contributors.json     ← credits / acknowledgements

        │  Next.js App Router API routes
        │  (src/app/api/  — cache: no-store)

Browser (React 19 + Zustand store)
  • Client polls content API at runtime
  • Zustand centralises fetched state
  • Framer Motion + Lenis deliver the visual experience
The sync step is mandatory. The repository does not ship mock data, so src/data/*.json files will be absent (or empty) until npm run sync succeeds. See Quickstart for step-by-step instructions.
The admin panel (/admin) exposes two additional sync mechanisms: a one-click manual sync button (backed by src/app/api/admin/) and a node-schedule cron job that can be configured from the admin UI and persisted in src/config/admin.json.

Architecture Overview

The src/ directory is divided into five top-level concerns:
src/
├── app/                    # Next.js App Router pages and API routes
│   ├── admin/              # /admin — login page + protected route group
│   ├── api/admin/          # Admin API: login, manual sync
│   ├── creation/           # /creation route
│   ├── map/                # /map route
│   ├── layout.tsx          # Global layout: local font registration + viewport frame
│   ├── page.tsx            # Homepage: envelope screen + scroll section group
│   ├── loading.tsx
│   └── not-found.tsx

├── components/             # UI building blocks by domain
│   ├── ui/                 # Shadcn-style primitives (do not modify logic directly)
│   ├── shared/             # Cross-route components: EnvelopeIntro, GuideLine,
│   │                       # CustomScrollbar, GlobalNav, TransitionOverlay
│   ├── motion/             # Animation components: MagneticButton, StickyCursor,
│   │                       # useMousePosition
│   ├── sections/           # Homepage scroll sections: AboutProject, AboutUs,
│   │                       # Credits, Footer, ScrollSections
│   ├── desktop/            # Desktop-only map and story card components
│   ├── mobile/             # Mobile-only stamp-collection waterfall components
│   └── creation/           # Creation board sticky-note waterfall

├── lib/                    # Core logic and shared utilities
│   ├── admin/              # Auth, scheduler, config read/write
│   ├── sync-service.ts     # Feishu + OSS sync service (shared by CLI and API)
│   ├── types.ts            # Domain types — single source of truth
│   ├── store.ts            # Zustand global state
│   ├── hooks.ts
│   ├── useVirtualScroll.ts # Lenis wrapper
│   ├── useLuge.ts          # Luge global init (smooth scroll disabled)
│   ├── useFooterSnap.ts    # Footer snap via Lenis ScrollTo
│   └── content.ts / utils.ts

├── config/                 # Local runtime config (admin.json, locations.json)
├── data/                   # Sync artefacts: content.json, creation-board.json,
│                           # contributors.json  (git-committed as fallback)
└── scripts/                # sync-feishu.ts + Feishu/OSS debug scripts
The root-level agents/, .opencode/agents/, and .trae/skills/ directories hold collaboration assets for the development workflow. They are excluded from the TypeScript compilation scope in tsconfig.json and play no part in the runtime application.

Visual Design Language

The site’s aesthetic is intentionally restrained and paper-like:
  • Background: #ece9e4 — warm grey, evoking aged paper
  • Accent: #c23643 — wax-seal red, used for interactive highlights
  • Heading font: ChillDINGothic_SemiBold (locally hosted OTF)
  • Body font: ZouLDFXKAJ (locally hosted TTF)
  • Viewport frame: 5 px white border + 16 px border radius wrapping the entire viewport, reinforcing the “private photograph” metaphor
The design system is built with Tailwind CSS v4 and Shadcn-style Radix UI primitives, with all motion work handled exclusively by Framer Motion v12 and Lenis.

Build docs developers (and LLMs) love