⭐ Zero JS runtime • Pre-rendered HTML • Incremental builds • Custom URLs • 6 themes • Accessible everywhere • Templates

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 engine, create a post, build, preview $ git clone https://brew.bsd.cafe/stefano/GoodReader.git $ cd GoodReader && npm install $ node cli.js init my-blog $ node cli.js post my-blog my-first-post $ node cli.js serve my-blog 386 unchanged, 0 files compressed Build complete in 0.14s Dev server running at http://localhost:8080/

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.

6 Built-in Themes

Default (dark/sepia/light toggle), Terminal (retro monospace), Newspaper (classic broadsheet), Book (elegant reading), Solarized (precision palette), and Vintage (warm aged-paper). All zero JS.

Built-in Dev Server

Preview your site instantly with node cli.js serve. No Python or external tools needed. Supports custom ports with --port. Builds first, then serves - one command to see your changes.

Incremental Build Cache

Enable incrementalBuild for large sites and edit loops. Good Reader reuses unchanged Markdown parses, rendered pages, related-post data, Markdown HTML, static assets, and gzip files while rebuilding only dependent output.

Content Management CLI

Create, edit, delete, and list posts and pages from the terminal with post, page, edit, delete, and list commands. New posts auto-generate full front matter and open your $EDITOR. When that editor is vi, you'll get a friendly guide to :wq.

Tag Archives & Affinity

Automatic tag pages, tag index grid with counts, per-tag RSS feeds, and "You may also like" related posts using IDF-weighted tags plus TF-IDF content similarity. Related vectors are cached for fast rebuilds.

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.

Paginated Homepage

Optional pagination splits the homepage into multiple pages. Configurable posts-per-page. Generates /page/2/, /page/3/, etc. Client-side search still searches all posts regardless of pagination.

Custom URL Patterns

Configurable URL structure for posts via urlPattern. Choose from /:year/:month/:day/:slug/, /blog/:slug/, /posts/:year/:month/:slug/, or any combination of :year, :month, :day, :slug, :hour, :minute, and :second tokens.

Template Profiles

Switch between template profiles with templateProfile in config. Default (search, theme toggle, images), Minimal (content-only, no JS), Reader (text-first, reading-focused), or Newspaper (lead-article homepage). Each inherits from the next - override only what you need.

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). With incremental builds, unchanged files keep their existing .gz siblings instead of being compressed again.

60+ BSSG Themes

Use any of the 60 BSSG themes via automatic CSS conversion, alongside 6 built-in themes. 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

Six built-in themes: Default (dark/sepia/light toggle), Terminal (retro), Newspaper (broadsheet), Book (elegant), Solarized (precision palette), and Vintage (aged-paper). Or pick from 60+ BSSG themes.

Dark (Amber) built-in
Sepia built-in
Light built-in
Terminal built-in
Newspaper built-in
Book built-in
Solarized built-in
Vintage 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, or use node cli.js post my-blog my-title to auto-generate a template with all front matter fields and open your editor immediately. Drafts get a .draft suffix.

Build

Run node cli.js build my-blog to generate everything, or node cli.js serve my-blog to build and preview at http://localhost:8080/ with the built-in dev server. Turn on incrementalBuild for dependency-aware rebuilds that skip unchanged Markdown, templates, static files, related-post data, and gzip output. Tag archives, author pages, RSS feeds, sitemap - all generated in seconds. The engine and your content stay in separate directories.

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, template profile, related posts, RSS, authors, image downloads, compression, incremental caching, and every other feature.

config.json
{ "site": { "name": "My Blog" }, "theme": "default", "authorsPage": true, "relatedPosts": { "enabled": true, "count": 3 }, "compress": true, "incrementalBuild": true, "pagination": { "enabled": false, "postsPerPage": 9 }, "dateFormat": "long", "urlPattern": "/:year/:month/:day/:slug/", "templateProfile": "default" }

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, then uses a dependency-aware cache so no-op builds can skip parsing, rendering, related-post work, copies, and gzip compression.

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 the engine, init a site, drop in your Markdown, build, preview with the built-in dev server, then upload. Your personal blog, deployed in under two minutes.