AgentSkillsCN

frontend-asset-management

当您需要通过 R2 CDN 管道,以类型安全的方式导入静态资源(图片、字体、视频、3D 模型),并进行添加、引用或提供服务时,可使用此技能。

SKILL.md
--- frontmatter
name: frontend-asset-management
description: Use when adding, referencing, or serving static assets (images, fonts, videos, 3D models) through the R2 CDN pipeline with type-safe imports

Frontend: Asset Management

Static assets are content-hashed, synced to Cloudflare R2, and served via CDN. All asset references MUST be type-safe through the generated manifest.

Developer Workflow

code
1. Add file    →  assets/{folder}/{file}
2. Generate    →  pnpm fe:assets:gen
3. Use in code →  Assets_getAssetUrl("folder/file.png")
4. Sync to R2  →  pnpm fe:assets:push

Every step is mandatory. Skipping step 2 causes TypeScript errors. Skipping step 4 means assets won't load in deployed environments.

Directory Structure

code
spark/frontend/my-vite-app/
├── assets/                          # Source assets (committed to git)
│   ├── logo.svg
│   └── Page_Login/
│       ├── carousel-bg.png
│       └── slide-1.png
├── scripts/
│   ├── generate-asset-manifest.js   # Step 2: generates types
│   └── sync-assets-to-r2.js         # Step 4: uploads to R2
└── src/types/
    └── assets.types.ts              # Auto-generated (DO NOT edit manually)

Folder convention: Organize by page or feature, matching the Page_ naming convention (e.g., assets/Page_Login/, assets/Page_Dashboard/). Shared assets go in the root assets/ folder.

Type-Safe Asset Usage

tsx
import { Assets_getAssetUrl, type Assets_AssetPath } from "@/types/assets.types";

// ✅ Type-safe — autocomplete + compile-time validation
const url = Assets_getAssetUrl("Page_Login/slide-1.png");

// ✅ Type-safe in data structures
const slides: { image: Assets_AssetPath }[] = [
    { image: "Page_Login/slide-1.png" },
];

// ✅ Background images
<div style={{ backgroundImage: `url(${Assets_getAssetUrl("Page_Login/carousel-bg.png")})` }} />

// ✅ Image elements
<img src={Assets_getAssetUrl("logo.svg")} alt="Spark" />

Generated Exports (assets.types.ts)

ExportPurpose
Assets_AssetPathUnion type of all valid asset paths
Assets_MANIFESTMap: original path → hashed R2 key
Assets_METADATAMap: path → { hash, size, mimeType }
Assets_getAssetUrl(path)Full URL (dev: /assets/..., prod: CDN)
Assets_getHashedPath(path)Hashed R2 key only
Assets_getMetadata(path)Metadata for an asset

Environment Behavior

EnvironmentURL pattern
Development/assets/{original-path} (Vite dev server)
Production{VITE_CDN_BASE_URL}/{env}/assets/{hashed-filename}

Content hashing (logo.0206c431.svg) provides automatic cache busting — 1-year immutable cache headers on R2.

pnpm Scripts

bash
pnpm fe:assets:gen     # Regenerate assets.types.ts from assets/ folder
pnpm fe:assets:push    # Sync to R2 (interactive env prompt, or --env production)

Common Mistakes

  • ❌ Hardcoding asset paths: "/assets/logo.svg" → ✅ Assets_getAssetUrl("logo.svg")
  • ❌ Editing assets.types.ts manually → ✅ Run pnpm fe:assets:gen
  • ❌ Adding assets without regenerating → ✅ Always run gen after adding/removing files
  • ❌ Using <img src={require(...)}> or Vite import for assets → ✅ Use Assets_getAssetUrl()
  • ❌ Referencing assets not in assets/ folder → ✅ All static assets go through the pipeline

Supported File Types

Images (PNG, JPG, GIF, WebP, SVG, AVIF), Fonts (WOFF, TTF, OTF), Videos (MP4, WebM, MOV, AVI), Audio (MP3, WAV, OGG, FLAC, M4A), 3D Models (GLB, GLTF, FBX, OBJ, USDZ), Documents (PDF, TXT, CSV, JSON, XML).

Related Skills

  • cloudflare-wrangler-cli — R2 bucket and Workers deployment
  • frontend-environment-variablesVITE_CDN_BASE_URL configuration
<!-- Last created: 2026-02-08 -->