1650 λέξεις
8 λεπτά
AI 协作修改指南 (Agent Reference)
Αυτό το άρθρο δεν έχει μετάφραση στην τρέχουσα γλώσσα. Επιστροφή στην κύρια γλώσσα.
AI 协作修改指南 (Agent Reference)
如果你正在使用 AI 代码助手(如 GitHub Copilot, Cursor, Codeium, 或自定义 Agent)来协助你修改本项目,你可以直接让 AI 读取下方的全英文指令块。
这份英文指南包含了本项目(基于 Fuwari)的深层定制逻辑,包括:Docs 系统的层级原理、BGM 播放器的位置、多语言 (i18n) 的 Fallback 机制以及防冲突保护等。
这部分不仅包含了项目的架构和约束,也指示了 AI 遇到不可解决的情况时,去翻阅 Docs 里面的 Fuwari 教程。
让 AI 阅读这份指南后,它能极大地减少“修改代码后报错”或者“改错地方”的概率。
Prompt for AI Agents
请复制下方代码块内的所有内容,发送给你的 AI 助手,或者通过 @ 提及此文件让 AI 读取:
# Project Architecture & Modification ReferenceYou are acting as an AI coding agent modifying an Astro-based blog project. This project is built upon the "Fuwari" theme but contains heavy customizations including a Docs system, a persistent BGM player, and a strict i18n fallback mechanism.
Before proposing code changes, familiarize yourself with the following core systems:
## 1. Docs File System & Category Tree- **Directory**: `src/content/docs/[lang]/`. Subdirectories automatically create nested navigation categories.- **Ordering**: The navigation tree ordering is controlled by the `sidebar_position` property in the markdown frontmatter. - **Missing Position**: If a file lacks `sidebar_position`, it falls back to a lower priority. Files with `sidebar_position` will always appear above those without. For items without `sidebar_position`, folders are sorted above files, and then they are sorted alphabetically by filename. - **Conflict Error**: No two items (files or folders) within the same directory level can have the same `sidebar_position`. If a collision occurs, `content-utils.ts` will intentionally throw a `Sidebar position conflict!` Error and fail the build.- **Logic Location**: The logic that parses directories and builds the category tree is located in `src/utils/content-utils.ts` (specifically `getSortedDocsPosts` and `getCategoryTree`). If you need to modify how the sidebar is generated or sorted, edit `content-utils.ts`.
## 2. Persistent BGM (Music Player) System- **Implementation**: The music player uses Svelte and persists across page transitions because the project uses Swup for client-side routing, and the Navbar (which houses the player) is deliberately kept outside the Swup replacement container.- **Location**: `src/components/MusicPlayer.svelte`.- **Modification**: To change the audio source, do not look in `config.ts`. You must directly modify the `<audio src="...">` tag inside `MusicPlayer.svelte`.
## 3. Theme & Color Palette System- **Framework**: The project uses Tailwind CSS and OKLCH color spaces.- **Configurability**: Primary theme colors and preset hues are defined in `src/config.ts` under `siteConfig.themeColor`.- **Core CSS Variables**: The actual Tailwind variable mappings (like `--primary`, `--bg`, `--card`) are strictly defined in `src/styles/global.css`. If you are asked to change the fundamental UI colors (like dark mode backgrounds), modify `global.css`.
## 4. Strict i18n (Internationalization) SystemThe i18n system is heavily customized to support strict separation and graceful degradation.
**Crucial Distinction: Content i18n vs UI i18n**- **Content i18n (Articles/Docs)**: Governed by the file system. Translated posts and docs are physically placed in language-specific subdirectories like `src/content/blog/[lang]/` and `src/content/docs/[lang]/`. Translations are done directly in the `.md` or `.mdx` files.- **UI i18n (Components/Website Text)**: Governed by TypeScript dictionaries in `src/i18n/`. Used for static UI elements like buttons, navbars, and layout text. Translated via the `i18n(key, lang)` function. Do NOT hardcode UI text in components; always extract it to these dictionaries.
- **Dictionary & Fallback**: Handled in `src/i18n/translation.ts`. The `i18n(key, lang)` function attempts to find the translation in the target language. If missing, it **falls back to the main language** (`siteConfig.lang` defined in `config.ts`).- **Modular Partials & Plugin Auto-Prefixing**: Translations for specific UI parts (partials) are modularized under `src/i18n/partials/<folder_name>/`. - **Do NOT manually prefix keys with `[folder_name]`** inside `keys.ts` or the translation files. Use plain string values (e.g. `title = 'title'`). The custom Vite plugin (`i18nKeyPrefixPlugin.mjs`) automatically injects `[folder_name]` into the `keys.ts` AST at build time. - **Usage in Astro/React**: When fetching translations, pass the enum key directly: `i18n(HomeKey.title)`. Do NOT manually wrap it (e.g. `i18n(\`[home]${HomeKey.title}\`)`), as this will cause double-prefixing (`[home][home]title`). - **Fallback Peeling Mechanism**: If a key is completely missing, `translation.ts` gracefully degrades. Before returning the raw key as a string, it strips any leading `[...]` folder prefix using a regex (`/^\[.*?\](.*)$/`). If you accidentally double-prefix a key, this peeling mechanism will silently strip the first prefix and render the second one as raw text (e.g., `[home]title`), masking the actual error. Check for double prefixes if translations fail to load.- **Raw Key Output**: If a translation key is missing in the **main language**, the system no longer throws a build-time Error. Instead, it securely degrades by outputting the raw key itself, ensuring no empty or undefined UI elements disrupt the user experience.- **Adding Tags**: To add a new tag, you MUST register it in `src/i18n/i18nKey.ts` and add its translation to AT LEAST the main language file (e.g., `src/i18n/languages/zh_CN.ts`).- **Post Filtering (Hiding mechanism)**: Posts without a translation in the current language directory (e.g., `src/content/blog/en/`) are completely hidden from that language's feed. This filtering logic is executed in `src/utils/content-utils.ts` inside `getSortedPosts()`.- **Main Language Folder & Conflict**: For the main language (e.g., `zh_CN`), posts can be placed either in the root `src/content/blog/` or in `src/content/blog/zh_CN/`. Both map to the root routing without the language prefix. However, if two files share the same slug across these two locations, `content-utils.ts` will throw a conflict error during compilation to prevent silent overwriting.
## 5. MDX and UI Component Hydration- **Inserting Components**: If you are asked to insert a React/Vue/Svelte UI component into a post or documentation, you MUST use an `.mdx` file, not `.md`. You must `import` the component immediately below the frontmatter block.- **Hydration is Required**: Because Astro uses a Zero-JS by default architecture, UI framework components embedded in `.mdx` files are rendered as static HTML without event listeners. If the component has interactivity (e.g., `onClick`, state hooks), you MUST append an Astro client directive like `client:load`, `client:idle`, or `client:visible` when calling it (e.g., `<MyComponent client:load />`), otherwise the interactivity will completely fail.
## 6. Swup Routing & Persistent UI BoundariesThis project uses `@swup/astro` for client-side page transitions, but several UI regions are intentionally kept outside Swup replacement to preserve state.
- **Configuration Location**: Swup is configured in `astro.config.mjs`.- **Current Swup Containers**: The replacement containers should remain: - `main` - `#toc` - `#sidebar-bottom` - `#mobile-toc-container`- **Do Not Add These Containers Back**: - `#navbar-wrapper` - `#sidebar`- **Why Navbar Is Persistent**: `#navbar-wrapper` contains persistent interactive UI, including the BGM player, language selector, search trigger, and theme/color controls. Replacing it through Swup can reset component state and break i18n updates.- **Why Sidebar Is Persistent**: The left profile card should stay mounted. Only `#sidebar-sticky` is manually synchronized when the route crosses the Docs boundary.
### Sidebar Sync Rules- **Logic Location**: `src/components/widget/SideBar.astro`.- **Non-Docs -> Docs** and **Docs -> Non-Docs**: Fetch the target page HTML and replace only `#sidebar-sticky`.- **Docs -> Docs**: Do not fetch or replace the whole sidebar. Instead, dispatch `category-tree:update-url` with the new pathname.- **Non-Docs -> Non-Docs**: Do not touch the sidebar.- **Event Coalescing**: Swup and Astro can emit multiple events for one navigation. `SideBar.astro` uses `requestAnimationFrame` to coalesce events before comparing the previous and next path. Do not remove this without replacing it with equivalent deduplication.
### CategoryTree URL Recalculation- **Logic Location**: `src/components/widget/CategoryTree.svelte`.- **Expected Behavior**: On Docs internal navigation, the persistent `CategoryTree` receives the new URL and recalculates active/expanded state using `expandActive(categories, nextUrl)`.- **Important Rule**: Keep expansion based on the active path. Do not automatically expand every folder that has an `index.md`; `index.md` means the folder is readable, not that it should always be expanded.- **Completion Event**: After recalculating and awaiting Svelte `tick()`, the root tree dispatches `category-tree:updated`.
### Mobile Docs Scroll Timing- **Logic Location**: `src/layouts/Layout.astro`.- **Anchor**: Mobile Docs pages scroll to `#swup-mobile-scroll-target`.- **Critical Sequence**: For mobile Docs internal navigation, Swup automatic reset is disabled first, then `CategoryTree` recalculates expansion, then `category-tree:updated` triggers the final scroll. Scrolling before the tree expands will produce incorrect positioning.
### Language Switching Must Bypass Swup- **Rule**: Language switch links must use `data-no-swup`.- **Affected Areas**: Top language selector, post/doc language availability links, and fallback buttons such as "this article does not exist in this language, switch to another language".- **Reason**: Language switching changes persistent i18n state across Navbar, Search, DisplaySettings, date picker text, and other UI. Treat language changes as full page navigations, not Swup transitions.
## 7. Custom Astro & Vite Plugins- **Plugin System**: To keep `astro.config.mjs` clean, custom Vite or Astro build-time plugins (such as the automatic `i18nKeyPrefixPlugin` for modular partials) are stored in the `src/astro-plugins/` directory.- **Rule**: If you need to debug or extend compile-time transformations, look inside `src/astro-plugins/`. Do not write large inline plugin logic directly inside `astro.config.mjs`.
## 8. Troubleshooting & Fallback Context- **When Stuck**: If you encounter an unsolvable situation, an ambiguous requirement, or need to understand how a core feature (like friends configuration or modular i18n) was heavily customized, you MUST read the official user tutorials located in `src/content/docs/zh_CN/Fuwari/` and its `advanced-customization/` subdirectory.
Whenever you make structural changes, always ensure you respect the `sidebar_position` for Docs, update translation keys in the main language dictionary, and avoid breaking the Astro Content Collections schema. AI 协作修改指南 (Agent Reference)
https://aquamarine-z.github.io/el/docs/fuwari/advanced-customization/ai-guide/