AstroStarter

astro-biluo — Astro Starter Template

By Just-Passersby

Biluo is an Astro-based blog theme that uses Markdown/MDX content collections and includes Pagefind search, Giscus comments, light and dark modes, series and tag grouping, RSS/sitemap/llms.txt, and configuration for deploying static assets to Cloudflare Workers.

Explore the design

Compare the page layouts and mobile experience. Open any screenshot for a closer look.

1 previews
Author preview
Author-provided preview

Preview provided in the project README.

One original preview is available. Open the full image to inspect the design.

Screenshots show visual appearance; interactive behavior may differ.

Recorded 2026-10-02View source

What stands out

A quick read of the recorded project description.

01

Light water blue and dark night sky blue color schemes, with light/dark mode switching

02

Tags support nested groups, and series use a tree structure to organize posts

03

Pagefind full-text search index generated at build time, without relying on Google site: queries

04

Giscus comments are disabled by default and the provider can be replaced in src/data/comments.ts

05

Built-in RSS (with XSL styling), sitemap, llms.txt, and robots.txt

06

Provides wrangler.jsonc and cache header configuration for deployment to Cloudflare Workers Static Assets

Template Details

Biluo is a blog theme built with Astro. Content is managed through Markdown / MDX content collections and built as a static site. The theme provides two color schemes: light (water blue) and dark (night sky blue), supports a tag system with nested groups and a tree-structured series system; search uses Pagefind to generate an index at build time, and comments use Giscus, which is disabled by default and can be replaced with another provider. It also includes callouts (note / tip / important / warning / caution), GitHub-style footnotes, heading anchors, code block copy buttons, click-to-zoom images, reading time estimates, pinned posts, related posts, table of contents, pagination, RSS (with XSL styling), sitemap, llms.txt, robots.txt, a mobile drawer navigation, and a custom 404 page.

The theme is designed as single-language (i18n-ready rather than multilingual): all UI strings are centralized in src/i18n/ui.ts, siteLocale is the single source for the site language, og:locale, and date formatting, and the default language is Traditional Chinese. There is no per-post language switcher; multilingual content must be organized using tags and series.

The deployment target is Cloudflare Workers Static Assets (not Pages). wrangler.jsonc only sets assets and has no main. A custom 404 requires setting assets.not_found_handling: "404-page" in wrangler.jsonc; for cache headers, public/_headers sets immutable long-term caching for /_astro/* and /fonts/*, while HTML keeps the default so updates take effect immediately.

The code is MIT licensed, and the bundled fonts are SIL OFL 1.1 (each font has its own OFL.txt under public/fonts/; sources and copyright are in NOTICE). User-added content is not covered by the theme's MIT license; the footer renders a configurable content license, defaulting to All rights reserved.

The Markdown pipeline is currently based on Remark (configured via processor: unified({...}) in astro.config.mjs). The roadmap plans to switch after Sätteri is stable and its features can be fully reproduced; Remark is still used for now.

AstroStarter

Is it right for your project?

Use Cases

  • Building a personal blog with content written in Markdown / MDX
  • Organizing technical articles or serialized content by series and grouped tags
  • Wanting build-time full-text search without relying on an external search service
  • Planning to deploy a static site to Cloudflare Workers Static Assets
  • Needing RSS, sitemap, llms.txt, and other basic files for search engines and AI crawlers

Suitable For

  • Developers using Astro who prefer managing posts with content collections
  • Sites that need a single-language blog with centralized, replaceable UI strings
  • Sites that accept Giscus comments and want comments disabled by default
  • Deployers willing to adjust wrangler.jsonc and _headers according to the documentation

Getting started & customization

Use these recorded setup notes alongside the repository instructions for your chosen version.

  1. 1

    Install dependencies with pnpm install, and start the development server with pnpm dev (localhost:4321)

  2. 2

    pnpm build builds to ./dist/ and generates the Pagefind index; use CI=true pnpm build in CI or non-interactive environments

  3. 3

    pnpm preview previews dist via wrangler dev at localhost:8787, and pnpm deploy runs the build and wrangler deploy

  4. 4

    Site title, description, author, and posts per page are modified in src/consts.ts; posts go in src/content/blog/*.{md,mdx}

  5. 5

    A custom 404 requires setting assets.not_found_handling: "404-page" in wrangler.jsonc; if you rename the font directory, update @font-face and public/_headers accordingly

Read repository instructions

License & source material

Usage conditions & limitations

Free to use · keep license notice

This entry covers the free version under the MIT license in the public repository; the free scope is the code of this version and does not mean that external services or third-party assets are free.

Must comply with when using

  • You may use, modify, commercialize, and distribute the code of this version for free.
  • When distributing copies or substantial portions of the code, retain the original author's copyright notice and the full MIT license notice.
  • The code is provided as is; warranties and limitations of liability are governed by the original license and applicable law.

Additional costs & items to verify

  • Demo images, fonts, icons, and other third-party assets must be checked against their respective licenses; they cannot be judged solely by the code's MIT license.
  • External services such as domains, hosting, databases, payments, or AI may incur separate charges.
  • The comment feature uses Giscus and is disabled by default; enabling it requires configuration in src/data/comments.ts and obtaining the corresponding values from giscus.app, making it an optional feature that depends on an external service.
  • The deployment target is Cloudflare Workers static assets, which requires wrangler and depends on the Cloudflare platform; it is not ready to use out of the box on any static host.
  • The custom 404 page must have assets.not_found_handling set to "404-page" in wrangler.jsonc; otherwise production will return a blank 404.
  • The theme is designed as single-language (i18n-ready only, not multilingual); there is no per-post language switcher, and multilingual content must be organized using tags and series.
  • The default UI language is Traditional Chinese; for an English-first site, you must change defaultLang / siteLocale in src/i18n/ui.ts and translate the UI strings.
  • Content added by users is not covered by the theme's MIT license; the footer renders an All rights reserved content license by default, which can be changed to a license such as CC.
  • The footer displays an All rights reserved content license by default; to change it, set CONTENT_LICENSE in src/consts.ts and fill in license.* in src/i18n/ui.ts.
  • The bundled fonts use SIL OFL 1.1, which differs from the code's MIT license; each font has its own OFL.txt under public/fonts/, and sources and copyright are in NOTICE.
  • In non-interactive environments such as CI or agents, build with CI=true pnpm build; otherwise pnpm 11 will block on an interactive prompt.
  • The Markdown pipeline is currently based on Remark; the roadmap plans to switch after Sätteri reaches a stable release and its features can be fully reproduced, but Remark is still used for now.
View Original Text Basis

Permission is hereby granted, free of charge

Original License Text

**Comments**: Giscus, provider-swappable (see `src/data/comments.ts`); off by default

Original README

**Deploy**: Cloudflare Workers Static Assets (`wrangler`)

Original README

**Custom 404**: set `assets.not_found_handling: "404-page"` in `wrangler.jsonc`, otherwise the custom 404 only works in `pnpm dev` and returns a blank 404 in production.

Original README

The theme is **single-locale by design** (i18n-*ready*, not multilingual).

Original README

The shipped default is Traditional Chinese (`zh-Hant`).

Original README

**Content** — yours. Anything you add under `src/content/` and `src/assets/` is not covered by the theme's MIT license.

Original README

The footer renders a configurable content license (default **All rights reserved**).

Original README

**Fonts** — SIL Open Font License 1.1. Each font ships its own `OFL.txt` under `public/fonts/`; sources and copyright are listed in `NOTICE`.

Original README

In non-interactive environments (CI / agents) build with `CI=true pnpm build` > (pnpm 11 otherwise blocks on an interactive prompt).

Original README

The plan is to switch it to [**Sätteri**](https://github.com/bruits/satteri) — a Markdown/MDX processor that parses and compiles in Rust while running plugins in JavaScript, built on the same unified (Remark/Rehype) ecosystem — once it reaches a **stable release** and its surrounding packages mature.

Original README
https://github.com/Just-Passersby/astro-biluo/blob/main/LICENSEhttps://github.com/Just-Passersby/astro-biluo/blob/main/README.md

Compiled by DeepSeek based on repository license and README ·2026-10-04. Results only cover the materials read; dependencies, images, fonts, and subsequent term changes are subject to their respective original texts.

Project checks & description sources

Template Information

Source platforms
Astro Themes
Documentation and maintenance reference score
Partly documented · 63 / 100
Technologies
Astro
Website type
Starter
How this score is calculated

Our heuristic uses license records (up to 30), a demo link (12), a preview (10), stars (15), recorded maintenance (15), description completeness (8), feature records (5) and classification data (5). It is not a code, security or performance test, or a Google score. A link does not establish tested functionality.

What to verify for this project

Repository update recorded
2026-10-01
Screenshot last checked
2026-10-04

No demo link is recorded. Use the repository instructions to evaluate the project locally; the screenshot alone cannot establish interactive behavior.

The catalog identifies Astro as the primary stack. Check the actual dependency manifest and lockfile for versions and hosting requirements. These notes use recorded metadata, not a code audit or a deployment test.

Use a selection guide →

How this description was prepared

AI-assisted description based on catalog records and repository material. Repository authors are not automatically the reviewers of this description.

Review declaration: [email protected] · 2026-10-04

Inspect the recorded source material

SHA-256: 273e0de0ba1d059c62a7442251decbf73d225726aeec4d68a1497137bb10d28e

2026-10-04T17:25:26.771Z

Source file / repository
English | [繁體中文](./README.zh-Hant.md)

<p align="center">
  <img src="./src/assets/avatar.png" width="140" alt="Biluo logo" />
</p>

<h1 align="center">Biluo (碧落)</h1>

<p align="center">
  <img src="./assets/banner.png" alt="Biluo — light and dark themes, split by the theme-toggle's circular reveal" />
</p>

A clean, performance-focused blog theme built with [Astro](https://astro.build)
and deployed to **Cloudflare Workers Static Assets**. Content is authored in
Markdown / MDX content collections, search is powered by Pagefind, comments by
Giscus, with dark mode, a tree-structured series system, grouped tags, RSS /
sitemap / llms.txt, and an i18n-ready single-locale design.

> The name **碧落 / Biluo** comes from the classical Chinese term for the *azure
> heavens*, echoing the theme's water-blue (light) and night-sky-blue (dark)
> palette.

> **Licensing at a glance:** the theme source code is MIT (see `LICENSE`); the
> bundled fonts are SIL OFL 1.1 (see `NOTICE` and the `OFL.txt` files under
> `public/fonts/`); any content you add is your own. See [License](#license).

## Features

- Light / dark mode with water-blue / night-sky-blue palettes
- Tags with nested groups, and a tree-structured series system
- Full-text search via [Pagefind](https://pagefind.app) (build-time index, not Google `site:`)
- Callouts / admonitions (note / tip / important / warning / caution)
- GitHub-style footnotes (label localized), heading anchor links
- Code-block copy button, click-to-zoom images, reading-time estimate
- Pinned post, related posts, table of contents, pagination
- RSS (with styled XSL view), sitemap, `llms.txt`, `robots.txt`
- Default hero image fallback, `og:image` fallback to a post's hero
- Mobile drawer header, custom 404 page
- Centralized UI strings (i18n-ready, single-locale by design)

<p align="center">
  <img src="./assets/post.png" width="720" alt="A post page: table of contents, series navigation, localized callouts, and syntax-highlighted code" />
</p>
<p align="center"><sub>A post page — table of contents, series navigation, localized callouts, and code highlighting.</sub></p>

## Tech stack

- **[Astro](https://astro.build) 7** (`output: static`), Node 22+
- **Content**: Markdown / MDX content collections (`@astrojs/mdx`); GitHub alert
  syntax, heading anchors. The Markdown pipeline is configured in
  `astro.config.mjs` via `processor: unified({...})` (Astro 7's first-class
  integration point). `@astrojs/markdown-remark` is a load-bearing dependency.
- **Search**: [Pagefind](https://pagefind.app) (build-time index)
- **Images**: Astro `<Image>` + `sharp` (webp / resizing)
- **Comments**: Giscus, provider-swappable (see `src/data/comments.ts`); off by default
- **Deploy**: Cloudflare Workers Static Assets (`wrangler`)

## Quick start

| Command | Action |
| :--- | :--- |
| `pnpm install` | Install dependencies |
| `pnpm dev` | Dev server at `localhost:4321` (`astro dev`) |
| `pnpm build` | Build to `./dist/` (`astro build` + Pagefind index) |
| `pnpm preview` | Serve `dist` with `wrangler dev` at `localhost:8787` (closest to production) |
| `pnpm deploy` | Build and `wrangler deploy` |

> In non-interactive environments (CI / agents) build with `CI=true pnpm build`
> (pnpm 11 otherwise blocks on an interactive prompt).
>
> Check page count: `pnpm build && find ./dist -maxdepth 10 -type f | wc -l`

## Configuration (where to change what)

| What you want to change | File |
| :--- | :--- |
| Site title / description / author / posts-per-page | `src/consts.ts` |
| Posts | `src/content/blog/*.{md,mdx}` (frontmatter schema in `src/content.config.ts`) |
| Series (content) | `src/data/series.ts` (types / logic in `src/lib/series.ts`) |
| Tags taxonomy & groups | `src/data/taxonomy.ts` (types / logic in `src/lib/taxonomy.ts`) |
| Blogroll | `src/data/blogroll.ts` |
| Comments (Giscus) | `src/data/comments.ts` (values from [giscus.app](https://giscus.app)) |
| UI strings (i18n) | `src/i18n/ui.ts` |
| Site URL / Markdown pipeline / redirects / sitemap | `astro.config.mjs` |
| Cloudflare deploy (404 handling, assets dir) | `wrangler.jsonc` |
| Static-asset cache headers | `public/_headers` |

Post frontmatter fields: `title` (required), `description`, `pubDate`
(required), `updatedDate`, `heroImage`, `tags`, `pinned`.

**Where images go**: images that should go through Astro's optimizer (resize /
webp — hero / series / avatar) live in `src/assets/`; assets served verbatim
(favicon, fonts, `_headers`) live in `public/`.

## Documentation

Deeper guides live in [`docs/`](./docs/) (English and 繁體中文):

- [Content](./docs/en/content.md) — post frontmatter, the series data model,
  tags, and language facets.
- [Customization](./docs/en/customization.md) — color palette, fonts (swap or
  drop them), favicons.
- [Search](./docs/en/search.md) — how Pagefind indexes the site, and why search
  is blank in `pnpm dev`.
- [Comments](./docs/en/comments.md) — enabling Giscus and wiring up other
  providers.
- [Deployment](./docs/en/deployment.md) — Cloudflare Workers and other static
  hosts.
- [SEO and crawlers](./docs/en/seo-and-crawlers.md) — robots.txt and the
  AI-crawler policy, sitemap, social previews, `llms.txt`.

The demo posts under `src/content/blog/` also double as documentation.

## Project structure

```text
src/
├── assets/           # Astro-optimized images (hero / series / avatar)
├── components/       # Astro components (Header, SeriesCard, Comments…)
├── content/blog/     # Posts (Markdown / MDX)
├── content.config.ts # Post frontmatter schema
├── consts.ts         # Site-level settings
├── data/             # Content data: series / taxonomy / blogroll / comments
├── i18n/             # UI strings (ui.ts) and helpers (utils.ts)
├── layouts/          # Layouts (BaseLayout / BlogPost…)
├── lib/              # Data schema & logic (series / taxonomy)
├── pages/            # Routes (blog / series / tags / rss / 404…)
└── styles/           # Global styles (global.css)
public/               # Verbatim assets: favicon / fonts / _headers
astro.config.mjs      # site URL / Markdown pipeline / redirects / sitemap
wrangler.jsonc        # Cloudflare Workers Static Assets deploy config
```

## Deployment

This theme deploys to **Cloudflare Workers Static Assets** (not Pages;
`wrangler.jsonc` only sets `assets`, with no `main`). Two gotchas that differ
from Pages:

- **Custom 404**: set `assets.not_found_handling: "404-page"` in
  `wrangler.jsonc`, otherwise the custom 404 only works in `pnpm dev` and
  returns a blank 404 in production.
- **Cache headers**: the default is `max-age=0, must-revalidate`. `public/_headers`
  puts `immutable` long-cache on `/_astro/*` and `/fonts/*` (HTML stays on the
  default so it updates immediately). If you rename the font folder, update both
  the `@font-face` references and the `_headers` rules.

## Internationalization

The theme is **single-locale by design** (i18n-*ready*, not multilingual). All
UI strings live in `src/i18n/ui.ts`, and `siteLocale` there is the single source
of truth for the site's locale (`<html lang>`, `og:locale`, date formatting).
The shipped default is Traditional Chinese (`zh-Hant`).

To run an English-first site, change `defaultLang` / `siteLocale` in
`src/i18n/ui.ts` and translate the UI strings. There is no per-post language
switcher; to organize content in more than one language, use tags and series as
facets. (A demo post walks through this.)

## Roadmap

- **Remark → Sätteri.** The Markdown pipeline currently runs on Remark (via
  `processor: unified({...})` in `astro.config.mjs`). The plan is to switch it to
  [**Sätteri**](https://github.com/bruits/satteri) — a Markdown/MDX processor
  that parses and compiles in Rust while running plugins in JavaScript, built on
  the same unified (Remark/Rehype) ecosystem — once it reaches a **stable
  release** and its surrounding packages mature. The switch will only
  land once Sätteri is stable *and* every feature the current pipeline provides
  is verifiably reproduced on it, with no regression — until then, Remark stays.

## License

- **Code** — MIT (`LICENSE`).
- **Fonts** — SIL Open Font License 1.1. Each font ships its own `OFL.txt` under
  `public/fonts/`; sources and copyright are listed in `NOTICE`.
- **Content** — yours. Anything you add under `src/content/` and `src/assets/`
  is not covered by the theme's MIT license. The footer renders a configurable
  content license (default **All rights reserved**). To switch to a Creative
  Commons or other license, set `CONTENT_LICENSE` in `src/consts.ts` and fill in
  the `license.*` values in `src/i18n/ui.ts` (a CC BY-NC-ND example is included
  there as a comment).
Report a correction

Explore similar templates

Compare previews and descriptions within the same stack and category.