sarde

module
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 29, 2026 License: MIT

README

Sarde

Sarde

CI Latest Release Go Version

Documentation · Getting Started · Blog

A static site generator written in Go. Drop in Markdown, get a themed site. Ideal for product or API documentation, course materials, and blogs; conventions handle the structure, so the config file stays a few lines long.

Why Sarde

Sarde is a single Go binary with no runtime dependencies, and your directory structure is the site structure. Put files in content/docs/ and you get sidebar navigation, versioning, a table of contents, and search. A content/blog/ directory produces a date-sorted blog with RSS. Both layouts are selected by directory name alone, without additional configuration.

Defaults can be overridden through sarde.yaml, CLI flags, or environment variables.

Features

Content

  • Auto-detected collections: directory names select docs layouts with sidebar and ToC, date-sorted blogs, lab guides, or slide decks (see the table under Project structure)
  • Versioned docs (Docusaurus-style) with URL shadowing for the latest version
  • Optional sidebar.yaml for per-path sidebar overrides, tab overrides, and collapse_level
  • i18n with per-language directories, RTL support, and translation fallback
  • Title, date, and sidebar order inferred automatically from filenames, headings, and git history
  • Frontmatter in YAML, TOML, or JSON
  • Page bundles (directory with index.md + images) with automatic responsive image generation

Markdown

  • 30+ Goldmark extensions: code blocks with syntax highlighting (Kazari + Nuri), KaTeX math, Mermaid diagrams, GitHub-style alerts, callouts, cards, tabs, multi-column layouts, accordions, file trees, timelines, image comparison, keyboard shortcuts, spoilers, and more
  • Syntax highlighting via Kazari (Expressive Code-style frames, diff markers, line numbers) powered by Nuri (TextMate grammars, 257 languages)

Asset pipeline

  • CSS/JS bundling via esbuild (Go API, no Node.js)
  • Image processing: resize, crop, WebP conversion, LQIP blur-up placeholders (AVIF is available, but only in builds compiled with -tags avif; release binaries skip AVIF variants with a warning)
  • Content-hash fingerprinting for cache busting
  • HTML/CSS/JS minification

Built-in plugins (13 enabled by default)

  • sitemap, robots, rss, atom for standard web outputs
  • seo for Open Graph and Twitter Card meta tags
  • social_cards for server-side OG image generation
  • search for offline full-text search (Orama)
  • link_validator for internal/external broken link detection
  • content_lint for heading structure, image alt text, and frontmatter validation
  • katex, mermaid for math and diagram asset injection
  • redirects for redirect stubs (HTML or Netlify _redirects)
  • llms_txt for LLM-friendly site index

Client-side plugins (11 available, all opt-in)

Add any of these to plugins.enabled to bundle its CSS and JS. Nothing ships to the browser unless it is listed, and each one is injected only on pages that need it.

scroll-to-top, copy-section-link, external-links, image-lightbox, keyboard-nav, focus-mode, reading-progress, search-highlighter, text-highlighter, reading-position-memory, reading-preferences

External plugins

  • Install third-party plugins into plugins/{slug}/ with sarde plugin install, from a zip, directory, URL, or GitHub repo
  • Plugins are declarative (plugin.yaml manifest, assets, templates), so installing one never executes third-party code at build time
  • plugins.disabled turns off any plugin, built-in or external, without replacing the whole plugins.enabled list
  • Premium plugins are unlocked by an offline ed25519-signed license file (sarde license install). A missing or invalid license warns and skips the plugin; it never fails the build
  • The plugin manifest and license file formats are provisional for 1.0 and may change in a 1.x release

Developer experience

  • Dev server with WebSocket live reload and incremental rebuilds
  • Link checking with terminal, JSON, and GitHub Actions annotation output
  • Content validation without building (sarde validate)
  • Fenced-block syntax checking (sarde check-syntax)
  • Merged configuration inspection with provenance (sarde effective-config)
  • Obsidian vault importer (converts wikilinks and callouts)
  • Deploy command for GitHub Pages, or any custom command (rsync, provider CLIs) via the custom provider

Installation

Homebrew (macOS/Linux):

brew install getsarde/sarde/sarde

Shell script (macOS/Linux):

curl -sSfL https://raw.githubusercontent.com/getsarde/sarde/main/install.sh | sh

Binary download:

Grab the latest release from GitHub Releases. Available for Linux (amd64), macOS (amd64, arm64), and Windows (amd64).

From source:

go install github.com/getsarde/sarde/cmd/sarde@latest

Quick start

# Create a new site
sarde new site my-site
cd my-site

# Add some content
mkdir -p content/docs
echo '---
title: Getting Started
---

# Hello

This is your first page.' > content/docs/getting-started.md

# Start the dev server
sarde dev

Open http://localhost:4727. The docs/ directory is auto-detected as a docs collection, so you get a sidebar, table of contents, and prev/next navigation out of the box.

To build for production:

sarde build

Output goes to dist/ by default.

Project structure

my-site/
  content/              # Your Markdown files (required)
    blog/               # Auto-detected as blog collection
    docs/               # Auto-detected as docs collection
    _index.md           # Homepage content (optional)
  public/               # Copied as-is to output
  icons/                # Local SVG icons
  themes/               # Custom themes (optional)
  plugins/              # Installed external plugins (optional)
  sarde.yaml            # Configuration (optional)
  sidebar.yaml          # Sidebar overrides (optional)
  kazari.config.yaml    # Code block presentation (optional)

Collections are detected by directory name:

Directory names Type Default sort Layout
blog, posts, articles, news Blog date descending Feed with pagination
docs, documentation, guides, reference, courses, tutorials, lessons, workshops Docs sidebar.order ascending Three-column with sidebar + ToC
labs Labs sidebar.order ascending Lab guide with progress and objectives
slides, presentations, decks Slides date descending Presentation deck with gallery landing
Anything else Generic title ascending Default

These names are a convention, not a requirement. Any directory name works, and an unrecognized name becomes a generic collection. To get docs behavior under a different name, set it explicitly under collections: in sarde.yaml rather than renaming the directory.

Configuration

All configuration goes in sarde.yaml. Every option has a sensible default; the file is entirely optional. Values are resolved in a 5-layer cascade (last wins):

  1. Embedded defaults (compiled into the binary)
  2. theme.yaml from the active theme
  3. sarde.yaml in your project root
  4. CLI flags (--baseURL, --drafts, --future)
  5. Environment variables (SARDE_SITE_TITLE, SARDE_BUILD_OUTPUT, etc.)

Here is a minimal configuration:

site:
  title: My Project
  url: https://example.com

theme:
  dark: true

And a more complete example:

site:
  title: My Project
  url: https://example.com
  description: Project documentation and blog
  edit_url: https://github.com/user/repo/edit/main/content

theme:
  preset: docs
  dark: true

build:
  minify: true
  last_updated: git    # "git", "mtime", or "false"

collections:
  docs:
    versioning:
      enabled: true
      last_version: v2
      versions:
        - id: v2
          label: v2.x (latest)
        - id: v1
          label: v1.x

i18n:
  default_language: en
  languages:
    en:
      name: English
    fr:
      name: Français

plugins:
  # Listing `enabled` replaces the default set, so name every plugin you want.
  enabled:
    - sitemap
    - rss
    - search
    - seo
    - link_validator
    - scroll-to-top     # client-side plugins are opt-in
  # `disabled` turns off individual plugins without replacing the list above.
  disabled:
    - social_cards

See the default configuration for every available option and its default value.

Commands

sarde build                            # Build for production
sarde dev                              # Dev server with live reload (port 4727)

sarde new site <path>                  # Scaffold a new project
sarde new <collection> <title>         # Add a page to a collection
sarde new course <name>                # Create a course directory
sarde new lesson <course> <name>       # Add an auto-numbered lesson

sarde check-links                      # Validate links without building
sarde check-syntax                     # Check fenced-block syntax
sarde validate                         # Validate config and content
sarde effective-config                 # Print merged config with provenance

sarde deploy                           # Deploy to configured provider
sarde theme list|add|remove|eject      # Manage themes
sarde theme info|chromastyles          # Inspect a theme, dump Chroma styles
sarde plugin list|install|remove|info  # Manage external plugins
sarde license install|list             # Manage premium plugin licenses
sarde icons add|list                   # Download/list Iconify icon sets
sarde i18n add-language|status         # Manage languages (also remove-language, scaffold)
sarde doc-version create|delete|update # Manage docs versions

sarde import obsidian <vault>          # Import an Obsidian vault
sarde update                           # Self-update the binary
sarde version                          # Print version info

Global flags: --config/-c, --baseURL, --drafts/-D, --future, --verbose/-v, --quiet/-q

Architecture

Three layers:

  1. Interface: the CLI (Cobra) drives everything through ProjectManager, a unified API over the engine rather than direct file access
  2. Engine: seven-phase pipeline: Initialize, Discover, Parse (parallel), Assemble, Assets, Render (parallel), Write
  3. Plugins: four lifecycle hooks run in order: ConfigSetup (serial), ContentLoaded (serial), BeforeRender (serial per page), BuildDone (parallel)

The engine is designed around Go interfaces (ContentDiscoverer, FrontmatterParser, MarkdownRenderer, TemplateEngine) so each pipeline stage is independently testable.

Building from source

# Development build
go build -o dist/sarde ./cmd/sarde

# With version tag
go build -ldflags "-X github.com/getsarde/sarde/internal/version.Version=1.0.0" -o dist/sarde ./cmd/sarde

# Cross-compile
GOOS=linux   GOARCH=amd64 go build -o dist/sarde-linux ./cmd/sarde
GOOS=darwin  GOARCH=arm64 go build -o dist/sarde-macos ./cmd/sarde

# Tests
go test ./...

# Benchmarks (in-process, over synthetic sites)
go test -bench=. -benchmem -timeout 300s ./internal/build/

On Windows, build.bat wraps these commands: build.bat build, build.bat test, build.bat release.

For end-to-end build benchmarks (median wall time over a generated ~1,000 page fixture, pages/sec, per-phase timings, peak RSS, and an optional Hugo comparison), see benchmarks/README.md.

Performance

Current baseline (GitHub Actions ubuntu-latest, cold cache, median of 5 runs over the generated ~1,000 file fixture, 2,041 built pages):

Metric Value
Median wall time 35.1 s
Pages/sec 58
Peak RSS 931 MB

The numbers come from benchmarks/baseline.json, seeded from CI. Methodology, per-phase timings, and the update procedure are in benchmarks/README.md.

Tech stack

  • Core: Go, Goldmark, Cobra, Chroma v2, esbuild (Go API), fsnotify, go:embed
  • Generated sites: Pure HTML/CSS with ~1KB inline JS, no framework runtime
  • Search: Orama (offline, embedded in output)
  • Minification: tdewolff/minify (HTML), esbuild (CSS/JS)

Contributing

Contributions are welcome. Please open an issue to discuss significant changes before submitting a pull request.

# Clone and build
git clone https://github.com/getsarde/sarde.git
cd sarde
go build ./cmd/sarde

# Run tests
go test ./...

# Test against the example site
cd testsite/general
../../sarde dev

Acknowledgments

Sarde's docs collection offers feature parity with Docusaurus and Starlight, whose conventions inspired it. The code block rendering is powered by Kazari, a Go port of Expressive Code.

License

MIT


Documentation: getsarde.github.io/sarde | Default config reference: sarde.yaml

Directories

Path Synopsis
cmd
sarde command
sarde-bench command
Command sarde-bench measures sarde build performance over a fixture site.
Command sarde-bench measures sarde build performance over a fixture site.
internal
asset
Package asset handles CSS/JS bundling, image optimization, and content-hashed asset pipelines.
Package asset handles CSS/JS bundling, image optimization, and content-hashed asset pipelines.
atomicwrite
Package atomicwrite provides atomic file write operations via temp-file + rename.
Package atomicwrite provides atomic file write operations via temp-file + rename.
build
Package build orchestrates the full site build pipeline.
Package build orchestrates the full site build pipeline.
buildlock
Package buildlock provides an exclusive, crash-safe lock on a build output directory so two sarde processes cannot write into the same dist/ at once (a second dev server or a build racing a dev server silently corrupts fingerprinted assets; see my-docs/handoffs/dev-server-asset-404-handoff.md).
Package buildlock provides an exclusive, crash-safe lock on a build output directory so two sarde processes cannot write into the same dist/ at once (a second dev server or a build racing a dev server silently corrupts fingerprinted assets; see my-docs/handoffs/dev-server-asset-404-handoff.md).
cli
component
Package component provides the ComponentRegistry for component overrides.
Package component provides the ComponentRegistry for component overrides.
content/markdown/extensions/blockutil
Package blockutil provides shared helpers for container-style block directive parsers.
Package blockutil provides shared helpers for container-style block directive parsers.
content/markdown/extensions/codediff
Package codediff is a stub extension for organizational completeness.
Package codediff is a stub extension for organizational completeness.
content/markdown/extensions/genericdirective
Package genericdirective is the goldmark side of site- and theme-authored generic directives (internal/directive): one block parser and renderer handle every registered ::: directive, dispatching on the fence name.
Package genericdirective is the goldmark side of site- and theme-authored generic directives (internal/directive): one block parser and renderer handle every registered ::: directive, dispatching on the fence name.
directive
Package directive implements site- and theme-authored generic directives: data-driven ::: blocks defined by a directives/<name>.yaml schema, an <name>.html html/template, and an optional <name>.css sidecar.
Package directive implements site- and theme-authored generic directives: data-driven ::: blocks defined by a directives/<name>.yaml schema, an <name>.html html/template, and an optional <name>.css sidecar.
editor
Package editor provides safe, auditable file edits for user content.
Package editor provides safe, auditable file edits for user content.
license
Package license implements offline verification of ed25519-signed license files for premium external plugins.
Package license implements offline verification of ed25519-signed license files for premium external plugins.
navigation
Package navigation builds sidebar nav trees, breadcrumbs, and prev/next links for docs-layout collections.
Package navigation builds sidebar nav trees, breadcrumbs, and prev/next links for docs-layout collections.
plugin
Package plugin implements the 4-hook plugin lifecycle system and built-in plugins.
Package plugin implements the 4-hook plugin lifecycle system and built-in plugins.
plugin/announcements
Package announcements provides a built-in plugin that renders dismissible announcement banners at the bottom of every page.
Package announcements provides a built-in plugin that renders dismissible announcement banners at the bottom of every page.
plugin/catalog
Package catalog assembles the machine-readable plugin catalog behind `sarde plugins --format json`: every plugin name the engine accepts in plugins.enabled, with metadata and configurable fields.
Package catalog assembles the machine-readable plugin catalog behind `sarde plugins --format json`: every plugin name the engine accepts in plugins.enabled, with metadata and configurable fields.
plugin/clientplugins
Package clientplugins provides a declarative manifest-driven loader for client-side plugins.
Package clientplugins provides a declarative manifest-driven loader for client-side plugins.
plugin/external
Package external loads declarative disk-based plugins from {project}/plugins/{slug}/.
Package external loads declarative disk-based plugins from {project}/plugins/{slug}/.
plugin/katex
Package katex provides a built-in plugin that ships KaTeX runtime assets and wires them into any page whose rendered HTML contains math markup.
Package katex provides a built-in plugin that ships KaTeX runtime assets and wires them into any page whose rendered HTML contains math markup.
plugin/mermaid
Package mermaid provides a built-in plugin that ships Mermaid runtime assets and wires them into pages whose rendered HTML contains a mermaid diagram (class="sarde-mermaid").
Package mermaid provides a built-in plugin that ships Mermaid runtime assets and wires them into pages whose rendered HTML contains a mermaid diagram (class="sarde-mermaid").
plugin/serverplugins
Package serverplugins is the declarative registry of Sarde's built-in server-side plugins: manifest.yaml carries their metadata and defaults/<name>.yaml their configurable fields, in the same blueprint shape used by clientplugins and external plugin blueprints.
Package serverplugins is the declarative registry of Sarde's built-in server-side plugins: manifest.yaml carries their metadata and defaults/<name>.yaml their configurable fields, in the same blueprint shape used by clientplugins and external plugin blueprints.
plugin/telescope
Package telescope provides a built-in plugin that adds a command-palette style quick-navigation modal, opened with Ctrl+/ (Cmd+/ on Mac).
Package telescope provides a built-in plugin that adds a command-palette style quick-navigation modal, opened with Ctrl+/ (Cmd+/ on Mac).
project
Package project provides the ProjectManager API that bridges the desktop app and CLI to the site engine.
Package project provides the ProjectManager API that bridges the desktop app and CLI to the site engine.
server
Package server provides the dev server with HTTP serving, file watching, and WebSocket live reload.
Package server provides the dev server with HTTP serving, file watching, and WebSocket live reload.
taxonomy
Package taxonomy aggregates tags, categories, and other taxonomies across all pages.
Package taxonomy aggregates tags, categories, and other taxonomies across all pages.
template
Package template provides the Go html/template engine with custom functions and template lookup resolution.
Package template provides the Go html/template engine with custom functions and template lookup resolution.
theme
Package theme handles theme discovery, loading, token resolution, and CSS generation.
Package theme handles theme discovery, loading, token resolution, and CSS generation.
updatesign
Package updatesign verifies ed25519 signatures on release artifacts for the self-update flow.
Package updatesign verifies ed25519 signatures on release artifacts for the self-update flow.
tools
sarde-license-sign command
Command sarde-license-sign is the vendor-side license signing tool.
Command sarde-license-sign is the vendor-side license signing tool.
sarde-release-sign command
Command sarde-release-sign is the vendor-side release signing tool.
Command sarde-release-sign is the vendor-side release signing tool.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL