- Astro 39.1%
- CSS 25%
- TypeScript 22.3%
- JavaScript 13.3%
- Dockerfile 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
Build and publish image / build-and-push (push) Successful in 25s
|
||
| .forgejo/workflows | ||
| scripts | ||
| src | ||
| .dockerignore | ||
| .gitignore | ||
| .prettierrc | ||
| AGENTS.md | ||
| astro.config.mjs | ||
| DESIGN.md | ||
| Dockerfile | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.json | ||
Personal Site
A content-focused personal website and blog built with Astro. It supports regular posts, series posts, Traditional Chinese typography, system-aware dark mode, and static generation.
Run
pnpm install
pnpm dev
The development server prepares complete local LXGW WenKai TC files under public/dev-fonts/ so new or unsaved Chinese text always uses the Kai typeface. These generated files are ignored by Git.
Run checks and create a production build with:
pnpm build
To mark every generated HTML page as under construction, enable the build-time banner:
CONSTRUCTION_MODE=true pnpm build
Leave CONSTRUCTION_MODE unset (or set it to false) for the normal build.
Production builds create a page-specific LXGW WenKai TC font subset with the bundled subset-font dependency.
The site includes paginated article, series, and tag directories, a recent-status timeline at /now, plus a short contact page at /contact. Series articles are available at /blog/{series}/{date}-{slug} and tag result pages at /tags/{tag}.
Series metadata lives in src/content/blog/{series}/index.md; articles inside that directory inherit the series slug from their path and do not repeat series frontmatter. Post slugs also come from the final directory segment, so a readable date-plus-slug path is the single source of truth. kind defaults to post, while a series index explicitly uses kind: series:
src/content/blog/site-guide/
├── index.md
└── 2026-08-15-article-feature-tour/
└── index.md
SEO
The production origin is configured in src/utils/site.ts. Astro uses it for canonical URLs, Open Graph metadata and generated 1200x630 PNG social cards, RSS, robots.txt, and sitemap.xml.
OG images are generated during the build at dist/og/; each HTML page has its own card, including article, series, tag, directory, About, Contact, home, and 404 pages. Series cards use the title, description, status, and accent from their series index.
Public contact destinations are configured in src/config/contact.ts; edit that file to update the links shown on /contact.
New posts ask for a lowercase slug such as article-feature-tour, create a directory such as 2026-08-15-article-feature-tour, and open the Markdown file automatically with ${EDITOR:-vim}. New files start as drafts until draft: false is set.
For a series article, the series index must already exist:
pnpm new:post -- "Article title" --series=site-guide
The command also accepts --slug=article-feature-tour when an interactive prompt is not convenient.
Recent-status entries live in src/content/now/<slug>/index.md. Use kind: period with start and end for an overlapping life stage, or kind: event with a dates array for one or more event days. Dates use YYYY, YYYY-MM, or YYYY-MM-DD; a period end may additionally use now. Put the entry's sole description in the Markdown body. Local images can be declared in an optional gallery array with src and alt.
List article titles, dates, series, draft status, and file paths with:
pnpm posts
Images
Each post is a content bundle. Keep its index.md and related images in the same directory, then reference images with a relative Markdown path:

For example:
src/content/blog/2026-08-15-article-feature-tour/
├── index.md
└── system-map.png
Images in article content can be clicked or focused with the keyboard to open the zoom preview.
Write two or more Markdown image lines without blank lines between them to render a shared photo gallery. Its zoom preview includes previous/next controls; adding a blank line or any other content starts a new image group.
License
MIT License. See LICENSE.