# termi-blog

Monorepo for the Termi blog system.

## Structure

```text
.
├─ admin/      # React + shadcn admin workspace
├─ frontend/   # Astro blog frontend
├─ backend/    # Loco.rs backend APIs
├─ mcp-server/ # Streamable HTTP MCP server for articles/categories/tags
├─ deploy/     # Deployment manifests (docker compose/env examples)
├─ .codex/     # Codex workspace config
└─ .vscode/    # Editor workspace config
```

## Run

### Recommended

From the repository root:

```powershell
pnpm dev
```

This starts `frontend + admin + backend` in a single Windows Terminal window with multiple tabs.

Common shortcuts:

```powershell
pnpm dev:mcp
pnpm dev:frontend
pnpm dev:admin
pnpm dev:backend
pnpm dev:mcp-only
pnpm stop
pnpm restart
pnpm test:ui
```

### PowerShell entrypoint

If you prefer direct scripts, use the single root entrypoint:

```powershell
.\dev.ps1
.\dev.ps1 -WithMcp
.\dev.ps1 -Only frontend
.\dev.ps1 -Only admin
.\dev.ps1 -Only backend
.\dev.ps1 -Only mcp
```

If you want a single service to be opened as a new Windows Terminal tab instead of running in the current shell:

```powershell
.\dev.ps1 -Only frontend -Spawn
```

Legacy aliases are still available and now just forward to `dev.ps1`:

```powershell
.\start-frontend.ps1
.\start-backend.ps1
.\start-admin.ps1
.\start-mcp.ps1
```

### Frontend

```powershell
cd frontend
pnpm install
pnpm dev
```

### Admin

```powershell
cd admin
pnpm install
pnpm dev
```

### Backend

```powershell
cd backend
$env:DATABASE_URL="postgres://postgres:postgres%402025%21@10.0.0.2:5432/termi-api_development"
cargo loco start --server-and-worker 2>&1
```

如果需要验证浏览器推送、异步通知、失败重试等 Redis 队列任务，本地不要只跑 `server`，要把 `worker` 一起带上；否则任务会停在 `queued`。

### Docker（生产部署，使用 Gitea Package 镜像）

补充部署分层与反代说明见：

- `deploy/docker/ARCHITECTURE.md`
- `deploy/caddy/Caddyfile.tohka.example`

```powershell
docker compose -f deploy/docker/compose.package.yml --env-file deploy/docker/.env up -d
```

当前 compose 默认启动：

- frontend: `http://127.0.0.1:4321`
- admin: `http://127.0.0.1:4322`
- backend api: `http://127.0.0.1:5150`

> 注意：`deploy/docker/compose.package.yml` 不内置 postgres/redis，需使用外部数据库与 Redis。

如果你不是直接用默认端口直连，而是走独立域名 / HTTPS / 反向代理，建议同时设置这些 compose 运行时变量：

- `INTERNAL_API_BASE_URL=http://backend:5150/api`
- `PUBLIC_API_BASE_URL=https://api.blog.init.cool`
- `PUBLIC_IMAGE_ALLOWED_HOSTS=cdn.example.com,pub-xxxx.r2.dev`
- `ADMIN_API_BASE_URL=https://admin.blog.init.cool`
- `ADMIN_FRONTEND_BASE_URL=https://blog.init.cool`

可复制 `deploy/docker/.env.example` 为 `deploy/docker/.env` 后，至少设置：

- `DATABASE_URL`
- `REDIS_URL`
- `JWT_SECRET`

如需覆盖镜像 tag：

```powershell
$env:BACKEND_IMAGE="git.init.cool/<owner>/termi-astro-backend:latest"
$env:FRONTEND_IMAGE="git.init.cool/<owner>/termi-astro-frontend:latest"
$env:ADMIN_IMAGE="git.init.cool/<owner>/termi-astro-admin:latest"
docker compose -f deploy/docker/compose.package.yml --env-file deploy/docker/.env up -d
```

### Gitea Actions Docker 发布

仓库已新增：`.gitea/workflows/backend-docker.yml`

需要在仓库里配置：

- Secrets
  - `REGISTRY_USERNAME`
  - `REGISTRY_TOKEN`
  - `INDEXNOW_KEY`（可选；如果要在主分支镜像发布后自动提交 IndexNow）
- Variables（可选）
  - `REGISTRY_HOST`（默认 `git.init.cool`）
  - `IMAGE_NAMESPACE`（默认仓库 owner）
  - `BACKEND_IMAGE_NAME`（默认 `termi-astro-backend`）
  - `FRONTEND_IMAGE_NAME`（默认 `termi-astro-frontend`）
  - `ADMIN_IMAGE_NAME`（默认 `termi-astro-admin`）
  - `FRONTEND_PUBLIC_API_BASE_URL`（frontend 镜像构建注入的浏览器侧 API 默认地址，默认 `http://localhost:5150/api`；运行时推荐优先使用 `PUBLIC_API_BASE_URL`）
  - `ADMIN_VITE_API_BASE`（admin 镜像构建注入的 API 默认地址，默认 `http://localhost:5150`；运行时可被 `ADMIN_API_BASE_URL` 覆盖）
  - `ADMIN_VITE_FRONTEND_BASE_URL`（admin 镜像构建注入的前台跳转默认基址，默认 `http://localhost:4321`；运行时可被 `ADMIN_FRONTEND_BASE_URL` 覆盖）
  - `ADMIN_VITE_BASENAME`（可选；如果 admin 要挂在 `/admin` 这类路径前缀下，构建时设置为 `/admin`）
  - `INDEXNOW_SITE_URL`（可选；自动提交 IndexNow 时使用的前台 canonical 域名，例如 `https://blog.init.cool`）
  - `INDEXNOW_PUBLIC_API_BASE_URL`（可选；如果站点公开 API 不是 `${INDEXNOW_SITE_URL}/api`，可在这里显式指定）

如果同时配置了 `INDEXNOW_KEY` + `INDEXNOW_SITE_URL`，主分支镜像发布成功后会自动执行一次：

```powershell
pnpm --dir frontend run indexnow:submit
```

用来把首页、文章、分类、标签、评测等 canonical URL 提交到 IndexNow。

### MCP Server

```powershell
.\dev.ps1 -Only mcp
```

Default MCP endpoint:

```text
http://127.0.0.1:5151/mcp
```

Default local development API key:

```text
termi-mcp-local-dev-key
```

The MCP server wraps real backend APIs for:

- Listing, reading, creating, updating, and deleting Markdown posts
- Listing, creating, updating, and deleting categories
- Listing, creating, updating, and deleting tags
- Reading and updating public site settings
- Rebuilding the AI index

## Repo Name

Recommended repository name: `termi-blog`
