> ## Documentation Index
> Fetch the complete documentation index at: https://help.helloazhenweb.top/llms.txt
> Use this file to discover all available pages before exploring further.

# 匿名生日祝福墙

> 访客在 /write 写下匿名生日祝福。祝福会保存到你的数据库，自动着色，并显示在首页祝福墙上。

祝福墙让任何人都可以在不注册账号的情况下留下一段生日祝福。访客进入 `/write`，输入留言并提交 — 祝福会被保存到 Supabase，并显示在首页的祝福墙上。每条留言都会被随机分配一个强调色，让整面墙看起来生动多彩。

## 写一条祝福

在任意浏览器中打开 `/write`。你会看到一个全屏表单，内含一个文本框和字数计数器。

<Steps>
  <Step title="输入你的祝福">
    最多可以写 500 个字符。文本框底部的计数器会随着输入实时更新。
  </Step>

  <Step title="提交">
    点击 **送上祝福**。应用会把你的祝福发送到 `/api/messages`。所有提交都是匿名的 — 不需要姓名或登录。
  </Step>

  <Step title="确认">
    提交成功后，表单会被一个确认页面替代。三秒后会自动跳转回首页，让你在祝福墙上看到刚才的留言。
  </Step>
</Steps>

## 校验与错误提示

请求发送前会进行客户端校验，API 端也会再做一次服务器端校验。

| 条件              | 错误信息                |
| --------------- | ------------------- |
| 内容为空或仅含空白字符     | `写点什么吧~`            |
| 内容超过 500 字符     | `太长了，控制在 500 字以内哦`  |
| 5 分钟内提交超过 3 条祝福 | `祝福太多啦，休息 5 分钟再发吧~` |

## 速率限制

API 对每个 IP 地址限制为 **每 5 分钟 3 条祝福**。IP 在存储前会通过 SHA-256 进行哈希处理，因此数据库中不会保存原始 IP 地址。

<Warning>
  速率限制基于 `x-forwarded-for` 和 `x-real-ip` 请求头。请确保你的托管平台正确传递这些请求头。如果两者都缺失，所有请求都会落到 `"unknown"` 这个键下，共用同一个限制桶。
</Warning>

## 留言颜色

每条提交的留言会被随机分配六种 Tailwind 颜色之一：`rose`、`sky`、`amber`、`emerald`、`violet` 或 `pink`。颜色保存在 `color` 字段中，首页据此为每张卡片配色。

## API 参考

### GET /api/messages

返回最多 100 条留言，按时间倒序排列（最新的在前）。

**响应**

```json theme={null}
{
  "messages": [
    {
      "id": "uuid",
      "content": "Happy birthday!",
      "color": "rose",
      "created_at": "2026-05-24T10:00:00.000Z"
    }
  ]
}
```

<ResponseField name="messages" type="object[]" required>
  留言对象数组，按时间倒序排列。最多 100 项。

  <Expandable title="message properties">
    <ResponseField name="id" type="string" required>
      由 Supabase 生成的 UUID 主键。
    </ResponseField>

    <ResponseField name="content" type="string" required>
      祝福文本，已去除首尾空白。
    </ResponseField>

    <ResponseField name="color" type="string" required>
      取自 `rose`、`sky`、`amber`、`emerald`、`violet`、`pink` 中的一个。
    </ResponseField>

    <ResponseField name="created_at" type="string" required>
      留言写入时的 ISO 8601 时间戳。
    </ResponseField>
  </Expandable>
</ResponseField>

***

### POST /api/messages

提交一条新祝福。

**请求体**

<ParamField body="content" type="string" required>
  生日祝福文本。去除首尾空白后必须在 1 到 500 个字符之间。
</ParamField>

**响应状态码**

| 状态码 | 含义             |
| --- | -------------- |
| 201 | 留言创建成功。        |
| 400 | 校验失败（为空或过长）。   |
| 429 | 触发速率限制。        |
| 500 | 数据库错误或其他服务器错误。 |

**成功响应（201）**

```json theme={null}
{
  "message": {
    "id": "uuid",
    "content": "Wishing you the best birthday ever!",
    "color": "emerald",
    "created_at": "2026-05-24T10:00:00.000Z"
  }
}
```

**示例代码**

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://your-site.com/api/messages \
    --header 'Content-Type: application/json' \
    --data '{"content": "Happy birthday! Wishing you all the best!"}'
  ```

  ```javascript fetch theme={null}
  const response = await fetch('/api/messages', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ content: 'Happy birthday! Wishing you all the best!' }),
  });

  const data = await response.json();

  if (!response.ok) {
    console.error(data.error);
  } else {
    console.log('Wish submitted:', data.message);
  }
  ```
</CodeGroup>

## 管理后台

一个由密码保护的管理后台可以查看和删除留言。登录后可以从导航栏进入。后台会显示所有留言的时间戳、颜色，并提供删除任意条目的入口。

<Note>
  管理后台需要设置 `ADMIN_PASSWORD` 环境变量。详情见部署指南。
</Note>
