Astro博客

blog (puellamogica) — Astro 博客模板

作者 puellamogica

一个基于 Astro 的日文博客主题,面向《Project SEKAI》与角色暁山瑞希的内容,包含公开文章与密码保护的 vault 两类内容集合,并部署为 Cloudflare Worker。

看看你的网站会是什么样

浏览真实页面截图,比较内容排版与手机效果。点击下方缩略图切换,放大查看整页细节。

3 个预览视图
桌面端首页1 / 3
桌面端截图首屏预览

由服务器浏览器实际访问页面后截取。

全部页面与视图 3

截图用于了解视觉与布局,交互效果请以实际项目为准。

采集于 2026-09-30查看来源

值得关注的模板亮点

从已有项目资料中,快速了解它的特点。

01

两个内容集合:公开的 article 与密码保护的 vault,均为纯 Markdown(GFM)且 frontmatter 经过 schema 校验

02

vault 使用每篇文章独立的 argon2id 哈希、Cloudflare Turnstile 解锁挑战、D1 解锁会话与 TTL、按 IP 与 slug 的速率限制

03

Markdown 管线支持 GFM 脚注/表格/任务列表、KaTeX 数学公式、阅读时间、清理后的原始 HTML 与 eager 图片

04

代码块使用 Expressive Code 与 Kanagawa 明暗配色,支持可折叠区段与行号

05

渐进增强:Plyr 媒体播放器、PhotoSwipe 灯箱与 Swiper 画廊仅在用到它们的页面动态导入

06

内置 RSS、sitemap、robots.txt、Open Graph / Twitter 卡片,以及明暗主题即时切换

模板详细介绍

这个模板是 puellamogica/blog 的公开仓库,定位为日文博客主题,主题内容围绕《Project SEKAI》与角色暁山瑞希。它使用 Astro 构建,内容以纯 Markdown(GFM,不使用 MDX)编写,分为两个内容集合:公开的 article 与需要密码解锁的 vault。vault 的每篇文章使用 argon2id 哈希,解锁表单带 Cloudflare Turnstile 挑战,解锁会话存储在 D1 并带 TTL,同时有按 IP 与按 slug 的速率限制。Markdown 管线支持 GFM 脚注、表格、任务列表、KaTeX 数学公式、阅读时间、经过清理的原始 HTML 与 eager 图片;代码块使用 Expressive Code 与 Kanagawa 明暗配色,支持折叠区段与行号。站点还包含客户端分类/年份筛选(无 JavaScript 时仍可用)、来自独立爬虫 Worker 的天气快照(按 JST 显示)、按需动态导入的 Plyr、PhotoSwipe 与 Swiper,以及 RSS、sitemap、robots.txt 和 Open Graph / Twitter 卡片。路由除 login/[slug]、vault/[slug] 与 api/auth 为服务端渲染外,其余均预渲染。内容位于 git submodule 中,文章正文只使用 h2–h6,页面 h1 由布局负责。草稿在列表、RSS、sitemap 与生成路由中均被排除。

Astro博客

适合你的项目吗?

适用场景

  • 搭建以《Project SEKAI》与角色暁山瑞希为主题的日文博客
  • 需要将部分文章设为密码保护、并希望解锁流程有挑战与速率限制的写作场景
  • 希望用 Markdown 写作并自动获得 KaTeX 公式、GFM 扩展与代码高亮的博客
  • 部署到 Cloudflare Workers,并使用 Workers Assets、Cloudflare Images、KV 与 D1 的项目

适合人群

  • 熟悉 Astro、TypeScript 与 Cloudflare Workers 的开发者
  • 需要公开文章与密码保护内容并存的个人博客作者
  • 接受内容以 git submodule 方式管理、并愿意按 wrangler.jsonc 配置绑定的使用者
  • 需要 RSS、sitemap 与社交卡片等基础 SEO 输出的站点

上手与定制指南

结合仓库当前版本的说明,按下面的资料检查内容、配置与运行要求。

  1. 1

    使用 pnpm install 安装依赖,并通过 git submodule update --init 初始化内容子模块

  2. 2

    内容位于 src/content/article/<slug>.md(公开)与 src/content/vault/<slug>.md(密码保护),正文只使用 h2–h6

  3. 3

    vault 文章的 passwordHash 需用 pnpm hash:vault 生成,且必须与 VAULT_ARGON2_OPTIONS 匹配

  4. 4

    绑定、路由与速率限制在 wrangler.jsonc 中声明;密钥从 Cloudflare secrets store 读取,TURNSTILE_SITEKEY 为公开变量

  5. 5

    部署使用 pnpm deploy,Worker 绑定到 20190716.xyz 自定义域名;相关仓库包括 ../cron(天气爬虫)与 ../argon2(密码校验服务)

查看仓库使用说明

授权与来源资料

使用条件与限制

免费使用 · 保留许可声明

本次收录的是公开仓库中采用 Apache-2.0 许可的免费版本;免费范围为该版本代码,不代表外部服务或第三方素材免费。

使用时需要遵守

  • 允许免费使用、修改、商用和分发;分发时需随附 Apache-2.0 许可证。
  • 修改过的文件需显著标明改动,并保留相关版权、专利、商标及归属声明。
  • 若原项目附有 NOTICE 文件,分发衍生作品时需保留其中适用的归属声明。
  • 许可包含适用的贡献者专利授权;发起许可所述专利诉讼会终止该专利授权,且不授予商标使用权。
  • 代码按现状提供;担保与责任限制以原许可证及适用法律为准。

额外费用与待核对事项

  • 使用该模板需部署到 Cloudflare Workers,并依赖 Workers Assets、Cloudflare Images、KV 与 D1 等付费/需账号的 Cloudflare 服务,非纯静态托管。
  • vault 解锁表单依赖 Cloudflare Turnstile 挑战,需要配置 Turnstile 站点密钥与密钥,属于外部服务依赖。
  • 运行需在 Cloudflare secrets store 配置 ARGON2_ENDPOINT、ARGON2_HMAC_SECRET、VERCEL_PROTECTION_BYPASS、TURNSTILE_SECRET 等密钥,并需自建 argon2 校验服务。
  • vault 密码校验依赖独立的 ../argon2 HTTP 服务,该服务不在本仓库内,需自行部署。
  • 天气组件依赖独立的 ../cron Worker 抓取 OpenWeatherMap 生成 weather.json,需额外部署并可能涉及 OpenWeatherMap 账号/API 费用。
  • 内容以 git submodule 方式管理,需额外初始化子模块才能获得文章内容。
  • 仓库内 vendored 的 HTML 清理器来自 satteri-sanitize(MIT,© Ashish Vaghela),该部分代码适用 MIT 许可而非 Apache-2.0,再分发时需保留其版权与许可声明。
  • 演示图片、字体、图标及其他第三方素材需按各自许可核对,不能仅凭代码的 Apache-2.0 许可判断。
  • 域名、托管、数据库、支付或 AI 等外部服务可能另外收费。
查看原文依据

no-charge, royalty-free, irrevocable copyright license

许可证原文

Runtime:** Cloudflare Workers — Workers Assets, Cloudflare Images, KV (sessions), D1 (vault unlocks)

README 原文

a Cloudflare Turnstile challenge on the unlock form

README 原文

Secrets (`ARGON2_ENDPOINT`, `ARGON2_HMAC_SECRET`, `VERCEL_PROTECTION_BYPASS`, `TURNSTILE_SECRET`) are read from the Cloudflare secrets store

README 原文

**`../argon2`** — the HTTP service that verifies vault passwords.

README 原文

**`../cron`** — a Worker that crawls OpenWeatherMap and writes the `weather.json` snapshot the weather widget reads.

README 原文

git submodule update --init # content lives in a submodule

README 原文

The HTML sanitizer in `src/hast/sanitize/` is vendored from [`satteri-sanitize`](https://github.com/Ashish-CodeJourney/satteri-plugins/tree/main/packages/satteri-sanitize) (MIT, © Ashish Vaghela)

README 原文
https://github.com/puellamogica/blog/blob/master/LICENSEhttps://github.com/puellamogica/blog/blob/master/README.md

DeepSeek 根据仓库许可证和 README 整理 ·2026-10-01。结果仅覆盖已读取资料,依赖、图片、字体及后续条款变更以各自原文为准。

项目核对记录与介绍依据

模板资料

来源平台
GitHub
资料与维护参考分
资料一般 · 72 / 100
技术栈
Astro
网站类型
博客
这个分数如何计算

本站按许可资料(最高30分)、演示链接(12分)、预览图(10分)、Star数(15分)、记录的维护时间(15分)、描述完整度(8分)、功能记录(5分)和分类资料(5分)计算。它不是代码、安全或性能测试,也不是 Google 评分;有链接不代表已实测可用。

这个项目需要核对什么

记录的仓库更新时间
2026-09-29
截图检查日期
2026-10-01

已收录演示链接。请用你的内容与屏幕尺寸检查;有演示不代表表单、认证或支付已经可用。

目录记录的主要技术栈是 Astro。请通过依赖清单和锁文件核对实际版本与托管要求。这些说明基于收录资料,不代表代码审计或部署实测。

查看具体选型方法 →

介绍的制作与核对状态

介绍由 AI 辅助整理目录与仓库资料。仓库作者不等于这篇介绍的审核者。

已完成服务器许可规则与 AI 来源核对;未经过人工编辑审核。

查看当时使用的来源资料

SHA-256: 16a5d64083954fb3120896e7345bc69b9614c56c8a2fbbf510d30ca2eed01cde

2026-10-01T14:54:34.942Z

来源文件 / 仓库
# puellamogica/blog

An astro framework blog theme

A Japanese-language blog about _Project SEKAI_ and the character 暁山 瑞希, built with Astro and deployed as a Cloudflare Worker.

- **Site:** https://20190716.xyz
- **Stack:** Astro 7, TypeScript, Tailwind CSS v4, daisyUI 5
- **Runtime:** Cloudflare Workers — Workers Assets, Cloudflare Images, KV (sessions), D1 (vault unlocks)

## Features

- **Two content collections** — `article` (public) and `vault` (password-gated), both plain Markdown (GFM, no MDX) with schema-validated frontmatter.
- **Password-gated vault** — per-post argon2id hash, a Cloudflare Turnstile challenge on the unlock form, D1-backed unlock sessions with a TTL, and per-IP / per-slug rate limits.
- **Markdown pipeline** — GFM (footnotes, tables, task lists), KaTeX math, reading time, sanitized raw HTML, and eager images, all through one shared Sätteri processor.
- **Syntax-highlighted code** — Expressive Code with the Kanagawa light/dark pair, collapsible sections, and line numbers.
- **Post filter** — client-side category/year filtering that still works without JavaScript.
- **Weather widget** — a snapshot from a separate crawler Worker, normalized defensively and shown in JST.
- **Progressive enhancements** — Plyr media players, a PhotoSwipe lightbox, and a Swiper gallery, each dynamically imported only on pages that use them.
- **Feeds and metadata** — RSS, sitemap, `robots.txt`, and Open Graph / Twitter cards.
- **Light and dark themes** with an instant toggle.

## Project structure

```
├── migrations/            # D1 migrations (unlock table)
├── public/                # self-hosted static assets (icons, _headers)
├── scripts/               # authoring scripts (vault password hashing)
├── src/
│   ├── components/        # .astro components
│   ├── content/           # git submodule: article/, vault/, assets/
│   ├── data/              # categories and the character profile
│   ├── hast/              # HAST plugins + vendored HTML sanitizer
│   ├── layouts/           # BaseLayout and BlogPost
│   ├── mdast/             # MDAST plugins (KaTeX, reading time, question)
│   ├── pages/             # routes
│   ├── scripts/           # client-side enhancements
│   ├── styles/            # Tailwind entry and theme tokens
│   └── utils/             # pure, unit-tested helpers
├── test/                  # Vitest unit tests
├── astro.config.mjs
└── wrangler.jsonc
```

Path aliases: `@components/*`, `@layouts/*`, `@utils/*`, `@assets/*`.

Routes are prerendered except the gated ones: `login/[slug]`, `vault/[slug]`, and `api/auth` are server-rendered.

## Getting started

```sh
pnpm install
git submodule update --init   # content lives in a submodule
pnpm dev                      # http://localhost:4321
```

## Commands

| Command           | Action                                                        |
| :---------------- | :------------------------------------------------------------ |
| `pnpm dev`        | Start the dev server at `localhost:4321`                      |
| `pnpm build`      | Run `astro check` and build to `dist/`                        |
| `pnpm preview`    | Build, then preview the built Worker                          |
| `pnpm test`       | Run the Vitest suite (`vitestconfig.ts`)                      |
| `pnpm cf-typegen` | Regenerate `worker-configuration.d.ts` from `wrangler.jsonc`  |
| `pnpm hash:vault` | Interactively generate an argon2id hash for vault frontmatter |
| `pnpm deploy`     | Build and `wrangler deploy`                                   |

Lint TypeScript/JS with `pnpm exec eslint <files>` and CSS with `pnpm exec stylelint <files>`; Husky + lint-staged run both (plus Prettier) on commit.

## Writing content

Posts live in the content submodule under `src/content/article/<slug>.md` (public) or `src/content/vault/<slug>.md` (password-gated). Body content is GFM and uses `h2`–`h6` only — the layout owns the page `h1`. Per-post images sit next to the post in `src/content/assets/<collection>/<slug>/`.

Frontmatter fields, in addition to `slug`, `category` (`tech` / `life` / `notes`), `title`, `description`, `pubDate`, `updatedDate?`, `heroImage?`, `pinned`, and `draft`:

| Collection | Field          | Notes                                                                                         |
| :--------- | :------------- | :-------------------------------------------------------------------------------------------- |
| vault      | `question`     | Prompt shown on the unlock page (defaults to パスワードは何ですか?)                          |
| vault      | `passwordHash` | Required argon2id hash; must match `VAULT_ARGON2_OPTIONS`. Generate it with `pnpm hash:vault` |

Drafts are excluded everywhere — listings, RSS, sitemap, and generated routes.

## Configuration

Bindings, routes, and rate limits are declared in `wrangler.jsonc`:

- **Assets** (`ASSETS`) serve the built `dist/` output; **`IMAGES`** backs Cloudflare Images.
- **KV** (`SESSION`) stores sessions; **D1** (`DB`) stores vault unlocks (see `migrations/`).
- Secrets (`ARGON2_ENDPOINT`, `ARGON2_HMAC_SECRET`, `VERCEL_PROTECTION_BYPASS`, `TURNSTILE_SECRET`) are read from the Cloudflare secrets store, never from plaintext vars. `TURNSTILE_SITEKEY` is a public var.
- `ARGON2_PEPPER` is not a Worker binding: only the argon2 service holds the pepper, so nothing in the Worker reads it. It is read from the local shell by `pnpm hash:vault`, which must hash with the same pepper the endpoint verifies with.

Vault passwords are never verified in the Worker: the request is HMAC-signed and sent to a separate argon2 service, so no hashing code is bundled.

## Deployment

```sh
pnpm deploy
```

The Worker is bound to the `20190716.xyz` custom domain.

## Related repositories

- **`../cron`** — a Worker that crawls OpenWeatherMap and writes the `weather.json` snapshot the weather widget reads.
- **`../argon2`** — the HTTP service that verifies vault passwords.

## Credits

- Scaffolded from the [Astro blog starter](https://github.com/withastro/astro/tree/main/examples/blog), itself based on [Bear Blog](https://github.com/HermanMartinus/bearblog/).
- The HTML sanitizer in `src/hast/sanitize/` is vendored from [`satteri-sanitize`](https://github.com/Ashish-CodeJourney/satteri-plugins/tree/main/packages/satteri-sanitize) (MIT, © Ashish Vaghela); the KaTeX rendering under `src/mdast/` was extracted into this source the same way, from `satteri-katex`.

## License

Licensed under the Apache License, Version 2.0 — see [LICENSE](LICENSE).
反馈内容错误

看看同类模板

对比同技术栈与用途的模板,找到更适合的视觉与内容结构。