COS & CDN
Media resources (self-hosted images, covers, galleries, fonts, decorations, audio) all live in the Tencent Cloud COS Hong Kong bucket arsvine-cdn, served through the self-hosted CDN domain cdn.arsvine.com.
Buckets and permissions
- Public bucket: media resources
- Private bucket: versioned catalogs (
realm/catalog/**) plus resources that require a signed access cookie - Public bucket policy: public-read / private-write
- Private bucket policy: every read must be signed (access cookie)
- CORS: public bucket allows
https://arsvine.comand its subdomains, plushttp://dev.arsvine.com(local) for GET/HEAD - Referer allowlist:
arsvine.com,*.arsvine.com(localhost and empty Referer are rejected)
Object keys
Object key structure and examples:
<hash8> is the first 8 hex characters of the source file's SHA256, embedded in the object key (not only in the manifest). Same source always lands on the same object key, so cos sync can safely skip unchanged objects by etag.
<version> is the publish version stamp (UTC ISO without separators), e.g. 20260710T120000Z.
Version pointer
current.json is the active version pointer:
current.next.json is a pre-publish pointer written during the build; it is not flipped by the publish script. cos sync explicitly excludes both pointer files; scripts/assets-publish.mjs writes the real current.json in the last step with cos cp and Cache-Control: no-cache, max-age=0, must-revalidate.
The order is last-writer-wins:
- Upload immutable objects (images, audio, shared fonts)
- Upload the private catalog version directory
lsto verify bothassets.json/static-assets.jsonexist- Write the public
current.json - Write the private
current.json - Call
/api/revalidate-assetsto trigger ISR
If any earlier step fails the pointer is not flipped.
Cache-Control headers
Client read paths
- Self-hosted images (
og:image, post images, galleries): composed fromdata/site.tsassets.ogImageor a catalogobjectKeytohttps://cdn.arsvine.com/<key>, thennext/imagewithunoptimized={true}. - Fonts:
styles/globals.scssfont variables (--font-hudetc.) bind tohttps://cdn.arsvine.com/shared/fonts/google-fonts.css. - Media catalogs (home / works / collections / links / audio): at runtime the client calls
/api/assets/<section>; the handler reads the private bucketcurrent.json→ the version directory's<section>.json→ rewrites hashed object keys into fullhttps://cdn.arsvine.com/...URLs.
Critical invariants
- Never hard-code COS object keys in code. Every resource reference goes through the catalog.
- Never write private bucket paths into public docs. This page describes structure only, never instance names.
- Never put
current.jsonand catalog version directories in the samecos sync. The former usescos cpexplicitly; the latter usescos syncincrementally. - Local dev uses
dev.arsvine.com+scripts/dev-host-setup.cmdto solve the Referer check.