Development
Runtime
- Node.js:
24.x(production and the Vercel project setting).engines.nodeinpackage.jsonis the source of truth. - Package manager: pnpm (
packageManager: pnpm@11.7.0). - Framework: Pages Router. Do not switch to App Router.
- Server entry:
server.js(used in dev and production). Do not usenext dev/next start.
server.js loads .env.local, prepares Next, respects PORT, and handles graceful shutdown. proxy.ts is the locale middleware entry.
Quick start
Open http://localhost:3000. proxy.ts will 308-redirect / to /zh-CN (depending on NEXT_LOCALE cookie and Accept-Language).
Common commands
Single tests:
Vitest uses jsdom and matches **/*.test.ts. New tests live under tests/<area>/ with the six areas lib / components / hooks / i18n / pages / repo (GOTCHAS.md item 27). Do not put .test.ts next to source files.
Local COS Referer workflow
The cdn.arsvine.com bucket only allows Referer values matching arsvine.com / *.arsvine.com. Localhost and empty Referer are rejected.
To use real COS resources locally, the Windows helper handles hosts and proxy:
With -HostsOnly, open http://dev.arsvine.com in the browser; COS accepts the dev.arsvine.com Referer.
Local COS workspace
cos-workspace/ is a purely local working directory and must be gitignored.
pnpm assets:prepare expects cos-workspace/public-root-legacy/ to be a mirror of the current live public bucket. See website/asset-pipeline and website/cos-and-cdn for details.
Data and copy editing
For routine content changes prefer these files, not hard-coded values in components:
When adding a locale, update all of these:
i18n/config.ts(locales plus each map and helper)locales/<locale>.jsondata/<topic>/<locale>.tsfor every topiclib/i18n-data.tsstatic registryproxy.tslocale detection (if a new Accept-Language tag needs support)
Remote image host allowlist
Centralized in config/image-hosts.js, following Next.js images.remotePatterns spec:
Add or remove hosts only in this file. Do not duplicate the list in next.config.js.
Defaults and origins:
cdn.arsvine.com— Tencent COS Hong Kong bucketarsvine-cdn, serving self-hosted media, covers, galleries, and assetsplacehold.co— placeholders used bydata/*.tsimages.unsplash.com/source.unsplash.com— template sample images
For large content images, prefer direct cdn.arsvine.com URLs with next/image and unoptimized={true} to avoid burning Vercel Hobby Image Optimization quota and to avoid unnecessary /_next/image proxy traffic.
Font hosting
Realm self-hosts Google Fonts on cdn.arsvine.com/shared/fonts/ rather than fonts.googleapis.com, because Google Fonts is unreliable in mainland China. Three families:
Dosis300 / 400 / 500 (HUD UI)Noto Sans SC300 / 400 / 500 / 700 (CJK body plus some bold)Noto Serif SC400 / 700 (MDX reading)
data/site.ts fonts.googleStylesheet is the source of truth. After changing it:
Strict COS metadata:
The COS custom header Value field must hold only the value, never Cache-Control: .... A wrong value produces Cache-Control: Cache-Control: ..., Firefox rejects the font, and Traditional Chinese characters occasionally render as tofu. This is GOTCHAS.md item 3.
Before committing
At minimum:
For UI / interaction changes, also manually verify:
- Desktop and mobile layout
- Home → content → detail transitions
- Public and protected blog posts
- Mobile hash navigation to content sections
- Music player open / close / track switching
- Custom cursor hover labels and BACK state
- CJK and accented Latin character rendering