⭐ Zero JS runtime • Pre-rendered HTML • Accessible everywhere

Read Markdown.
Deploy static HTML.

Good Reader is a static site generator that reads your Markdown posts and produces a fully pre-rendered, deployable site. No server runtime. No JavaScript required. Works in Lynx.

terminal
# Clone, write, build, serve $ git clone https://brew.bsd.cafe/stefano/GoodReader.git my-blog $ cd my-blog $ $EDITOR contents/hello.md $ node build.js Build complete in 0.84s $ python3 -m http.server 8080 -d output

Everything you need, nothing you don't

A complete publishing toolchain for personal blogs and journals. Every page is real HTML with clean URLs, proper metadata, and semantic structure.

Markdown Posts

Write in Markdown with YAML front matter. Titles, dates, tags, slugs, featured images, descriptions, authors, and fediverse handles. Plain text content, zero build-time dependencies.

SEO & Discovery

Open Graph, Twitter Cards, JSON-LD structured data, canonical URLs, auto-generated sitemap.xml, robots.txt, and RSS feeds with real enclosure lengths. Built for search engines and social sharing.

Fediverse-Native

<meta name="fediverse:creator"> tags + <link rel="me"> profile verification. Site-wide defaults with per-author and per-post overrides. Multiple Mastodon handles supported.

4 Built-in Themes

Dark (amber), sepia, light - each toggleable, persisted in localStorage. No flash of unstyled content. Plus Terminal: fixed monospace, no toggle, zero JS.

Tag Archives & Affinity

Automatic tag pages, tag index grid with counts, per-tag RSS feeds, and "You may also like" related posts based on Jaccard similarity of tag sets.

Multi-Author

Per-post author overrides, authors index page, individual author pages with post listings, and per-author RSS feeds. All posts without an author assigned go to the site-wide author.

RSS & Atom Feeds

Full RSS 2.0 feeds with proper <content:encoded> namespace, real enclosure length and MIME type. Timezone-aware dates. Optional full-content mode. Per-tag and per-author feeds too.

Asset Precompression

Gzips every HTML, CSS, JS, JSON, RSS, and SVG file at build time (level 9). Upload to any static host - Netlify, GitHub Pages, Cloudflare Pages, an old VPS, anywhere.

60+ BSSG Themes

Use any of the 60 BSSG themes via automatic CSS conversion. Full layout passthrough - not just colors, but structural styling. From modern minimal to retro computing aesthetics.

BSSG Drop-in Compatible

All posts and pages are fully compatible with the BSSG format - swap between Good Reader and BSSG without changing a single Markdown file. Same front matter, same URL structure, same output semantics. Treat either one as your source of truth.

Client-Side Search

Instant full-text search powered by a generated data.json file. Tag-based filtering. All search runs in the browser - no external service, no tracking, no API keys.

Browser Post Editor

A full-featured, offline browser-based Markdown editor at /post-editor.html, just like BSSG. Live preview, auto-save, keyboard shortcuts, and your site's theme. Write posts right from the browser - no server required.

Text-Browser Friendly

Accessible in Lynx, Elinks, and other text browsers. Semantic HTML5, skip-to-content links, proper heading hierarchy, screen-reader labels, and ARIA attributes throughout.


Choose your aesthetic

Four built-in themes: dark, sepia, and light (toggleable), plus Terminal (fixed). Or pick from 60+ BSSG themes that transform the entire page layout, not just colors.

Dark (Amber) built-in
Sepia built-in
Light built-in
Terminal built-in

Three commands, a deployed blog

No build pipeline to configure. No plugin ecosystem to maintain. Just Markdown files and a Node.js build step.

Write

Drop Markdown files into contents/ with YAML front matter. Use the browser editor or your favorite terminal editor. Drafts get a .draft suffix.

Build

Run node build.js. Good Reader renders every post, generates tag archives, author pages, RSS feeds, sitemap, and compressed output in seconds.

Deploy

Upload the output/ directory to any static host. Clean URLs, no server rewrites needed. Every page is a real index.html file in its own directory.

Share

Fediverse meta tags are baked in. RSS feeds are live. Social previews work out of the box with featured images and SEO metadata pre-rendered into each page.


Simple JSON config

One file controls site name, theme, related posts, RSS, authors, image downloads, compression, and every other feature.

config.json
{ "site": { "name": "My Blog", "theme": "default" }, "authorsPage": true, "relatedPosts": { "enabled": true, "count": 3 }, "compress": true }

Why Good Reader and not BSSG?

The two were born years apart, for different reasons. I started BSSG more than ten years ago, kept it private for most of that time, and only released it about a year ago. Good Reader goes back roughly four years. I set it aside for a while, then picked it up again with one purpose: to make it a fast alternative to BSSG, one you could move to without rewriting a thing.

BSSG: simplicity and portability

Pure Bash. It runs almost anywhere, with nothing to install beyond a Markdown processor. It is the most compatible, lowest-maintenance choice. It favours simplicity and portability, and accepts that raw speed isn't the point.

Good Reader: performance first

On a large site, BSSG can get a little slow. That's where Good Reader steps in. It carries a few more dependencies, but the builds are far, far faster.

That's why Good Reader speaks BSSG's format exactly. Same Markdown, same front matter, same structure: move your content across, keep (roughly) the same theme, and switch back whenever you like. BSSG found its people, and I'm grateful for that. Good Reader wasn't built against it. It was built thanks to it.


Ready to publish?

Clone from Brew, drop in your Markdown, run the build, and upload. Your personal blog, deployed in under two minutes.