# 配置 (/docs/themes/yohaku/config)

# 配置项

Yohaku 的配置沿用 Shiro 的配置体系，在 Mix Space 后台「集成 - 代码片段」页面（原 配置与云函数）中，创建一条 `theme` 引用、名称为 `shiro` 的配置项（数据类型 JSON 或 YAML）。配置参考详见 [配置示例](#配置示例)。

<Callout type="info">
  Yohaku 复用了 `shiro` 这个配置键名，如果你从 Shiro 迁移到 Yohaku，无需更改配置名称。
</Callout>

## 第三方服务集成

LinkCard 解析、Open Graph 抓取，以及 TMDB、GitHub、Bangumi、NeoDB、arXiv、LeetCode、网易云音乐、QQ 音乐等外部内容的富化，全部由 Mix Space Core 后端的 enrichment 服务接管。

<Callout type="info">
  主题侧**不再需要**配置 `GH_TOKEN`、`TMDB_API_KEY` 等环境变量。所有第三方凭据统一在后台「设置 → 第三方服务集成」中维护。
</Callout>

进入后台「设置 → 第三方服务集成」，按主题中实际使用到的链接卡片类型，启用并填入对应凭据：

| Provider | 字段 | 说明 |
| --- | --- | --- |
| GitHub | `token` | 解析仓库、Issue、PR、Discussion、Commit 卡片，规避匿名访问的 rate limit |
| TMDB | `apiKey` | 解析 TMDB 影视链接 |
| Bangumi | `enabled` | 解析 Bangumi 番剧 / 书籍链接 |
| NeoDB | `enabled` | 解析 NeoDB 条目链接 |
| arXiv | `enabled` | 解析 arXiv 论文链接 |
| LeetCode | `enabled` | 解析 LeetCode 题目链接 |
| 网易云音乐 | `enabled` | 解析网易云音乐歌曲 / 歌单链接 |
| QQ 音乐 | `enabled` | 解析 QQ 音乐歌曲 / 歌单链接 |
| Open Graph | `enabled` | 抓取通用网页的 OG 元数据 |

后端完成富化并缓存后，主题端直接读取已结构化的数据进行渲染。

## 页脚信息 (`footer`)

此部分定义页脚的部分信息，主要包括备案、建站年份和页脚导航三部分。

### 备案信息 (`otherInfo.icp`)

**如何使用**: 根据示例，修改位于 `text` 的备案号以及备案号所指向的链接 `link`。

### 建站年份 (`otherInfo.date`)

**如何使用**: `{{now}}` 指向当前年份，其他略。

### 页脚导航 (`linkSections`)

分类包括 `name` 和 `links` 两个字段，对应分类名字及其下链接，其下链接又分为 `name`、`href`、`external` 三个字段，对应链接名字，指向链接和是否外链三个属性。

**如何使用**: 根据自己需要增删或修改特定链接及分类，需要注意如果指向外链的话需要加一行 `"external": true`。

## 站点信息 (`config.site`)

此部分包含了网站的基础信息设置，例如 favicon（网站图标）的配置。

### Favicon

- **`favicon`**: 设置网站在浅色模式下使用的图标。
- **`faviconDark`**: 设置网站在深色模式下使用的图标。

## Hero 部分 (`config.hero`)

`hero` 部分定义了网站首页的主要欢迎信息或介绍部分，这是访问者首次进入网站时看到的部分。

### Title 模板 (`title.template`)

包括多个元素（如 `span`, `code`, `h1` 等），每个元素都可以自定义文本内容和样式。

| 字段 | 类型 | 说明 |
|------|------|------|
| `type` | `string` | 渲染标签，如 `span`、`code`、`br`。`br` 表示显式换行。 |
| `text` | `string` | 文本内容。 |
| `class` | `string` | Tailwind CSS 类名。 |
| `style` | `object` | **推荐**。内联样式对象，可直接写 CSS 属性（如 `fontWeight`、`color`、`animation` 等），不依赖 Tailwind JIT 扫描，且能跟随 CSS 变量自动适配暗色主题。 |

**如何使用**: 修改 `text` 和 `style` 字段来自定义标题的文本内容和样式。你可以通过添加或删除元素来调整标题的结构。

### 描述 (`description`)

提供了对主页 `hero` 部分的简短描述。

**如何使用**: 直接修改 `description` 的值以更改介绍文本。

### 一言 (`hitokoto`)

提供自定义首页一言的功能。

接受一个对象，包含 `random` 和 `custom` 两个可选字段。

- 当存在 `random` 字段且值为 `true` 时，将会随机获取一言，优先级高于 `custom` 字段。
- 当存在 `custom` 字段时，将会使用自定义的一言。
- 如果两个字段都不存在，将会使用默认的一言。

```ts
interface Hitokoto {
  random?: boolean
  custom?: string
}
```

## 自定义脚本 (`config.custom`)

可以配置自定义的 CSS, Script。

### Scripts (`scripts`)

接受一个 [Script](https://nextjs.org/docs/app/api-reference/components/script#props) Props 参数数组。

### Styles (`styles`)

自定义 CSS。接受一个字符串数组。

### JavaScript tag (`js`)

自定义 JS 脚本。接受一个字符串数组。

### CSS href link (`css`)

加载外部 CSS，接受一个 CSS 外部样式表链接数组。

## 模块 (`config.module`)

此部分配置了网站的一些特定功能模块，比如活动跟踪、捐赠支持、社交媒体链接等。

### Live Desk (`liveDesk`) 模块

Live Desk 在站点顶部展示由 [Yohaku Companion](https://github.com/Innei/YohakuCompanion) 发布的最新应用和媒体状态。它使用 Mix Space Core 的 Companion Protocol v2、短期 lease 与实时 Gateway event，不依赖旧 `/fn/ps/update` 云函数。

```json
{
  "module": {
    "liveDesk": {
      "enable": true
    }
  }
}
```

支持 Companion Protocol v2 的 Core 默认提供 Live Desk，不需要额外的服务端环境变量。首次配置需要完成以下步骤：

1. 在后台 **Companion** 页面生成一次性配对码。配对码十分钟后过期，且只能使用一次。
2. 在 Yohaku Companion 的 **Settings → Yohaku** 中填写站点公开 URL、设备名称和配对码。
3. 检查 **Current Sanitized Preview**，再显式启用 Live Desk。完成配对本身不会开始公开状态。
4. 将主题配置中的 `config.module.liveDesk.enable` 设为 `true`。

Application、可选 Window Title 和 Media Playback 会先经过本地 source switch、Privacy & Rules 与 Alias，再作为一个原子快照发送。媒体播放进度仅在服务端 capability 声明支持 `mediaTimeline` 时启用；pause、睡眠、锁屏、移除设备或退出应用时会发起清除，lease 到期是最终兜底。

<Callout type="warning">
  Window Titles 可能包含文档名或会话名，默认关闭。只有在应用内显式开启后，Yohaku Companion 才会请求辅助功能权限并读取当前标题。
</Callout>

### 实时活动 (`activity`) 模块

- **`enable`**: 控制模块是否启用。
- **`endpoint`**: 指定活动更新的服务器端点。

**如何使用**: 这是兼容旧 ProcessReporter 云函数的路径。若仍需使用，将 `enable` 设为 `true` 并设置 `endpoint`；新部署应优先使用上方 Live Desk。

### 捐赠 (`donate`) 模块

- **`enable`**: 控制捐赠模块是否启用。
- **`link`**: 提供捐赠页面的链接。
- **`qrcode`**: 提供一或多个捐赠二维码图片的链接。

**如何使用**: 启用捐赠功能，并提供捐赠链接或捐赠二维码，以便支持者可以直接进行捐赠。

### 社交媒体 (`bilibili`) 模块

- **`liveId`**: b 站直播间 ID

### OpenPanel 模块

[OpenPanel](https://openpanel.dev) 是一个开源的网站分析工具。

- **`enable`**: 控制 OpenPanel 功能是否启用。
- **`id`**: OpenPanel 的 ID。
- **`url`**: OpenPanel 的访问地址。

**如何使用**: 如果你使用 OpenPanel 进行网站分析，通过这些配置连接并启用面板。

### 文章列表设定 (`posts`)

- **`mode`**: 文章列表的预览模式。可选值：`"loose"`（默认）、`"compact"`

两个模式，紧凑模式和松散模式。

### RSS 配置 (`rss`)

- **`noRSS`**: 设为 `true` 可禁用 RSS 输出。
- **`custom_elements`**: 自定义 RSS 元素数组。

### 签名动画 (`signature`) 模块

- **`svg`**: 签名的 SVG 代码。
- **`animated`**: 是否启用动画效果，默认为 `true`。

**如何使用**: SVG 代码可通过 [此网站](https://danmarshall.github.io/google-font-to-svg-path/) 生成。

<Callout type="warning">
  受限于 JSON 语法规则，SVG 代码需替换所有的 `"` 为 `\"`，否则会报错。
</Callout>

### OG 图片 (`og`)

- **`avatar`**: 自定义 Open Graph 图片中的头像 URL。

### 订阅 (`subscription`)

- **`tg`**: Telegram 频道链接，用于展示订阅入口。

## 配置示例

```json
{
  "footer": {
    "otherInfo": {
      "date": "2020-{{now}}",
      "icp": {
        "text": "萌 ICP 备 20236136 号",
        "link": "https://icp.gov.moe/?keyword=20236136"
      }
    },
    "linkSections": [
      {
        "name": "关于",
        "links": [
          { "name": "关于本站", "href": "/about-site" },
          { "name": "关于我", "href": "/about" },
          {
            "name": "关于此项目",
            "href": "https://github.com/Innei/Yohaku",
            "external": true
          }
        ]
      },
      {
        "name": "更多",
        "links": [
          { "name": "时间线", "href": "/timeline" },
          { "name": "友链", "href": "/friends" }
        ]
      },
      {
        "name": "联系",
        "links": [
          { "name": "写留言", "href": "/message" },
          { "name": "GitHub", "href": "https://github.com/innei", "external": true }
        ]
      }
    ]
  },
  "config": {
    "color": {
      "light": ["#33A6B8", "#FF6666", "#26A69A", "#fb7287", "#69a6cc"],
      "dark": ["#F596AA", "#A0A7D4", "#ff7b7b", "#99D8CF", "#838BC6"]
    },
    "site": {
      "favicon": "/favicon.svg",
      "faviconDark": "/favicon-dark.svg"
    },
    "hero": {
      "title": {
        "template": [
          {
            "type": "span",
            "text": "Hi, I'm ",
            "style": { "fontWeight": 300, "opacity": 0.85 }
          },
          {
            "type": "span",
            "text": "Innei",
            "style": {
              "fontWeight": 500,
              "color": "var(--color-accent)",
              "letterSpacing": "-0.02em"
            }
          },
          {
            "type": "span",
            "text": " 👋",
            "style": {
              "fontWeight": 300,
              "display": "inline-block",
              "transform": "rotate(-8deg)"
            }
          },
          { "type": "br" },
          {
            "type": "span",
            "text": "A NodeJS Full Stack ",
            "style": { "fontWeight": 300, "opacity": 0.8 }
          },
          {
            "type": "code",
            "text": "<Developer />",
            "style": {
              "display": "inline-block",
              "fontFamily": "var(--font-mono)",
              "fontSize": "0.72em",
              "fontWeight": 500,
              "padding": "0.25em 0.55em",
              "borderRadius": "0.35em",
              "backgroundColor": "color-mix(in srgb, var(--color-accent) 10%, transparent)",
              "color": "var(--color-accent)",
              "border": "1px solid color-mix(in srgb, var(--color-accent) 22%, transparent)"
            }
          },
          {
            "type": "span",
            "style": {
              "display": "inline-block",
              "width": "2px",
              "height": "0.9em",
              "backgroundColor": "var(--color-accent)",
              "marginLeft": "2px",
              "animation": "blink 1.2s linear infinite"
            }
          }
        ]
      },
      "description": "An independent developer coding with love."
    },
    "module": {
      "liveDesk": {
        "enable": true
      },
      "activity": {
        "enable": false,
        "endpoint": "/fn/ps/update"
      },
      "donate": {
        "enable": false,
        "link": "",
        "qrcode": []
      },
      "bilibili": {
        "liveId": 0
      },
      "openpanel": {
        "enable": false,
        "id": "",
        "url": ""
      },
      "posts": {
        "mode": "loose"
      },
      "signature": {
        "svg": "",
        "animated": true
      }
    }
  }
}
```

<Callout type="info">
  请注意，这份配置你需要自行修改成符合你需求的内容。更多配置项的信息请参考上方各字段说明。

  配置也可写成 YAML 格式，此时数据类型应选择 `YAML`。
</Callout>